2012-03-30 79 views
0

我新望对Ruby和我试图写一个方法来动态地添加方法来N个现有的Ruby类方法,这里是我到目前为止有:红宝石:添加到现有的类

class Person 
end 

def attr_addr (target, attr) 
    target.send :attr_accessor, attr 
end 

bob = Person.new 

attr_addr(Person,"name") 

bob.name = "bob" 

但我得到:

private method `name=' for .... 

我在做什么错在这里? - 我完全使用错误的方法;-)?

+0

什么版本的红宝石? – DGM 2012-03-30 13:16:07

+0

ruby​​版本:1.9.2p290 – gordatron 2012-03-30 13:57:40

回答

3

您的原始代码适合我。总之,这里的另一种方式来写它:

def attr_addr(target, attr) 
    target.instance_eval "attr_accessor :#{attr}" 
end 

这是在行动中的IRB会议:

>> bob = Person.new 
=> #<Person:0x00000000df8798> 
>> bob.name = "bob" 
NoMethodError: undefined method `name=' for #<Person:0x00000000df8798> 
     from (irb):6 
     from /home/michi/.rbenv/versions/1.9.3-p0/bin/irb:12:in `<main>' 
>> attr_addr(Person, "name") 
=> nil 
>> bob.name = "bob" 
=> "bob" 
>> bob 
=> #<Person:0x00000000df8798 @name="bob"> 
+1

我在ruby 1.9.2p0中得到原始错误,但是你的代码有效。由于某些原因,原始代码使其成为私有方法,至少在某些红宝石中。 – DGM 2012-03-30 13:15:49

+0

我正在运行1.9.2p290(我猜:ruby -v)我会尝试这种方式,看看它是否使它成为公共方法。谢谢 – gordatron 2012-03-30 13:52:47

+0

这个工程很好,我希望避免使用eval,但我会在稍后解决。 – gordatron 2012-03-30 13:55:32

0

这对我的作品(红宝石1.8.7):

irb(main):001:0> class Person; end 
=> nil 
irb(main):003:0> Person.send :attr_accessor, :name 
=> nil 
irb(main):004:0> p = Person.new 
=> #<Person:0x7f9716bad768> 
irb(main):005:0> p.name = "test" 
=> "test" 
irb(main):006:0> p.name 
=> "test"