Я пытаюсь динамически определять методы, основанные на сопоставлениях XML. Это работает очень хорошо. Однако я хочу создать переменную экземпляра, которая является массивом динамически определенных методов.
Мой код выглядит примерно так
def xml_attr_reader(*args)
xml_list = ""
args.each do |arg|
string_val = "def #{arg}; " +
" xml_mapping.#{arg}; " +
"end; "
self.class_eval string_val
xml_hash = xml_list + "'#{arg}',"
end
self.class_eval "@xml_attributes = [] if @xml_attributes.nil?;" +
"@xml_attributes = @xml_attributes + [#{xml_list}];" +
"puts 'xml_attrs = ' + @xml_attributes.to_s;" +
"def xml_attributes;" +
" puts 'xml_attrs = ' + @xml_attributes.to_s;" +
" @xml_attributes;" +
"end"
end
Так что все работает, за исключением случаев, когда я вызываю xml_attributes для экземпляра, он возвращает ноль (и выводит 'xml_attrs =').
Хотя операторы put перед определением выводят правильный массив. (когда я создаю экземпляр экземпляра)
Обновление -
Кандадабоггу Решение ниже работает. Я действительно не объяснил свой вопрос полностью, хотя так вот больше информации. Я хочу вызвать xml_attr_reader в классе, который расширяет XmlConfig. По сути, я хочу, чтобы он работал так же, как attr_reader активной записи.
Принимая Кандадабоггу Раствор
class XmlConfig
def xml_attr_reader(*args)
args.each do |arg|
class_eval(<<-RUBY, __FILE__, __LINE__)
def #{arg}
xml_mapping.#{arg}
end
RUBY
end
unless respond_to?(:xml_attributes)
class_eval(<<-RUBY, __FILE__, __LINE__)
attr_accessor :xml_attributes
RUBY
end
(self.xml_attributes ||=[]).concat(args)
end
end
и
config = XmlConfig.new
config.xml_attr_reader("age", "name")
config.age #=> age
config.name #=> name
config.xml_attributes #=> ["age", "name" ]
config.xml_attr_reader("city")
config.city #=> city
config.xml_attributes #=> ["age", "name", "city"]
Что я действительно хочу, так это (где у меня был XmlConfig как модуль, а не класс в моей версии)
class Event < ActiveWhatever
extend XmlConfig
xml_attr_reader :age, :name
xml_attr_reader :email, :location
end
class PrivateEvent < Event
xml_attr_reader :owner, :password
end