2013-02-09 73 views
4

使用由散列定義的訪問器方法即時創建對象的最簡單方法是什麼?例如,如果我有一個哈希:使用訪問器方法即時創建對象

{foo: "Foo", bar: "Bar"} 

我希望有具有存取方法foofoo=bar,和分別bar=與初始值"Foo",和"Bar",一個對象。我能想到做的:

module ObjectWithAccessor 
    def self.new h; Struct.new(*h.keys).new(*h.values) end 
end 

o = ObjectWithAccessor.new(foo: "Foo", bar: "Bar") 
o.foo # => "Foo" 

但是,我並不需要他們的多個實例與同組特定的按鍵,而是希望與可能不同組的創建它的新實例每次關鍵字,因此每次爲每個對象創建一個新的類別Struct似乎是矯枉過正的,我想避免這種情況。有一個更好的方法嗎?

回答

11

OpenStruct已經提供你想要什麼:

require 'ostruct' 

o = OpenStruct.new foo: "Foo", bar: "Bar" 
o.foo #=> "Foo" 
o.bar #=> "Bar" 
o.bar = 'BAR' 
o.bar #=> "BAR" 

或者,如果你不想(像您可以用OpenStruct,你可以做這樣的事情能夠定義對象的創建之後的任意屬性:

class ObjectWithAccessor 
    def initialize attrs 
    attrs.each do |name, val| 
     singleton_class.send :attr_accessor, name.to_sym 
     public_send :"#{name}=", val 
    end 
    end 
end 

o = ObjectWithAccessor.new foo: "Foo", bar: "Bar" 
o.foo   #=> "Foo" 
o.bar   #=> "Bar" 
o.bar = 'BAR' 
o.bar   #=> "BAR" 
o.bsr = 'typo' #=> #<NoMethodError: undefined method `bsr=' for #<Object:0x007fa4160847f8>> 

這仍然沒有創建一個新類只使用一次,並避免的OpenStruct「開放性」。

+2

請注意,OpenStruct是「開放的」,允許您通過錯字創建新屬性,而不是更新現有的屬性。 – Phrogz 2013-02-09 19:53:55

+0

@Progrog好點。我添加了不允許的代碼(因爲它可能不被期望),同時還避免創建僅使用一次的類。 – 2013-02-09 23:35:22

+0

感謝您的編輯。更大。 – sawa 2013-02-10 03:55:15

相關問題