2012-03-30 109 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"