2011-07-19 6 views
77

のは、私は以下のハッシュがあるとしましょう:...Rubyのメタプログラミング:動的なインスタンス変数名

{ :foo => 'bar', :baz => 'qux' } 

私は動的オブジェクト内のインスタンス変数になるためにキーと値を設定することができる方法を

class Example 
    def initialize(hash) 
    ... magic happens here... 
    end 
end 

...私はモデル内で次のようになります...

@foo = 'bar' 
@baz = 'qux' 

答えて

145

お探しの方法はinstance_variable_setです。だから、:あなたのインスタンス変数名は(彼らはOPの一例であるとして)「@」に含まれていない場合

hash.each { |name, value| instance_variable_set(name, value) } 

あるいは、より簡単に、

hash.each &method(:instance_variable_set) 

、あなたはそれらを追加する必要があります、それは、より多くのようになります:

hash.each { |name, value| instance_variable_set("@#{name}", value) } 
+1

完璧、ありがとう! – Andrew

+15

1.9.3のために私のために働かなかった。代わりに 'hash.each {| k、v | instance_variable_set( "@#{k}"、v)} ' – Andrei

+0

すごくすごい! –

5

は、あなたは、私たちは、どのような場合には

:)泣きObject#instance_variable_getObject#instance_variable_setを見たいと思ってます。

ハッピーコーディング。

+0

はいえー、私は疑問に助けることができなかった...なぜ?いつこれを使うのがいいの? –

12
h = { :foo => 'bar', :baz => 'qux' } 

o = Struct.new(*h.keys).new(*h.values) 

o.baz 
=> "qux" 
o.foo 
=> "bar" 
+1

これはかなり面白いです...二番目の連鎖 '.new()'は何をしていますか? – Andrew

+2

@Andrew: 'Struct.new'はハッシュキーに基づいて新しいクラスを作成し、2番目の' new'はちょうど作成されたクラスの最初のオブジェクトを作成し、ハッシュの値に初期化します。 http://www.ruby-doc.org/core-1.8.7/classes/Struct.html – DigitalRoss

+2

を参照してください。これは、実際には構造体が作られているので、これを行う本当に素晴らしい方法です。 – Chuck

4

あなたはまた、存在しないインスタンスを設定することからユーザーを防ぐsendを使用することができます変数:

def initialize(hash) 
    hash.each { |key, value| send("#{key}=", value) } 
end 

使用sendあなたのクラスであった場合に、あなたのインスタンス変数のためのattr_accessorのようなセッター:

class Example 
    attr_accessor :foo, :baz 
    def initialize(hash) 
    hash.each { |key, value| send("#{key}=", value) } 
    end 
end 
関連する問題