2010-03-11 40 views
0

我想动态定义基于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它返回null(并打印出“xml_attrs =”)。

而定义之前的放置实际上打印出正确的数组。 (当我实例化实例时)


更新 - kandadaboggu解决方案如下工作。我真的没有完全解释我的问题,所以这里有更多的信息。我想在扩展XmlConfig的类中调用xml_attr_reader。基本上我希望它能够像活动记录的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"] 

kandadaboggu解决我真正想要的,这是(在那里我有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 

回答

1

这里是你修改后的问题的解决方案。现在

module XmlConfig 
    def self.included(base) 
     base.extend ClassMethods 
     base.class_inheritable_array(:xml_attributes) 
     base.xml_attributes = [] 
    end 

    module ClassMethods  
     def xml_attr_reader(*args) 
     args.each do |arg| 
      self.class_eval(<<-RUBY, __FILE__, __LINE__) 
      def #{arg} 
       xml_mapping.#{arg} 
      end 
      RUBY 
     end 
     self.xml_attributes = args 
     end 
    end 
    end 

可以include在任何一类的模块。

class Event < ActiveWhatever 
    include XmlConfig 
    xml_attr_reader :age, :name 
    xml_attr_reader :email, :location 
    end 


    class PrivateEvent < Event 
    xml_attr_reader :owner, :password 
    end 

让我们测试的结果:

Event.xml_attributes  # ->[:age, :name, :email, :location] 
PrivateEvent.xml_attributes # ->[:age, :name, :email, :location, 
          #     :owner, :password] 

e= Event.new(...) 
e.age  # -> 27 
pe= PrivateEvent.new(...) 
pe.owner # -> Will 
+0

优秀的答案。奇迹般有效。感谢坚持这一个,非常感谢。 – Will 2010-03-12 23:05:10

1

试试这个:

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"] 

注:所有方法都是实例方法。

+0

所以这几乎工程。它适用于在类中调用xml_attr_reader的情况。但是如果我有可能属性,我会多次调用该方法来保持我的行<80个字符。最后一次调用xml_attr_reader会覆盖xml_attributes。 我尝试连接@xml_attributes,但在此动态生成中访问时总是为零。 我也有继承问题,其中xml_attr_reader可能会在父级中调用。我是属性的列表是父母和孩子的联合。 感谢您的帮助,任何其他想法? – Will 2010-03-11 21:09:06

+0

我已经做了修改来解决这个问题。请让我知道这对你有没有用。 – 2010-03-11 21:39:24

+0

谢谢你尝试,但它不起作用。我在if(self.respond_to?(:xml_attributes))之后放置了一个print语句,但它永远不会被调用。 – Will 2010-03-11 22:16:43