2011-09-23 4 views
18

私はinstance_variableの作成を自動的に反映するように、ハッシュ(ネストされたハッシュ)からattr_readerを生成しようとしています。ここRuby:attribute_accessorを動的に生成します

私がこれまで持っているものです。

data = {:@datetime => '2011-11-23', :@duration => '90', :@class => {:@price => '£7', :@level => 'all'}} 


class Event 
#attr_reader :datetime, :duration, :class, :price, :level 
    def init(data, recursion) 
    data.each do |name, value| 
    if value.is_a? Hash 
     init(value, recursion+1) 
    else 
     instance_variable_set(name, value) 
     #bit missing: attr_accessor name.to_sym 
    end 
    end 
end 

しかし、私は:(

答えて

33

はあなたが上(プライベート)クラスメソッドattr_accessorを呼び出す必要があることを行うための方法を見つけることができませんEventクラス:

self.class.send(:attr_accessor, name) 

私はあなたがこの行に@を追加することをおすすめします:

instance_variable_set("@#{name}", value) 

ハッシュで使用しないでください。

data = {:datetime => '2011-11-23', :duration => '90', :class => {:price => '£7', :level => 'all'}} 
+0

あなたは私の新しい親友です!!!!それはちょうど働く、とてもシンプルです... Rubyは魔法です:)そしてあなたは星です:)(私はしばらくのために私は幸せです) –

+0

もっと簡単な質問があります。アクセサー名のハッシュを含むので、my_class.class.priceなどを呼び出すことができます。 –

+0

まず、 'class'は予約済みのキーワードです。使用しないでください。ここでのコメントの2番目の質問は、この特定の質問の範囲を超えています。新しい質問は、属性アクセサーではなく、再帰などを扱うので、始めることもできます。 (PS、最善の答えを受け入れることを忘れないでください) – rdvdijk

1

attr_accessorはクラスメソッドであり、クラスで呼び出す必要があります。プライベートメソッドなので、クラスオブジェクトがselfのコンテキストで呼び出す必要があります。例として

class C 
    def foo 
    self.class.instance_eval do 
     attr_accessor :baz 
    end 
    end 
end 

、そのインスタンスCのインスタンスを作成し、そのインスタンスにfooを呼び出した後 - および将来のすべてのインスタンスを - 方法bazbaz=を含むであろう。

3

あなたはmethod_missingを使用して、この問題を解決するためのメタ魔法のビットを行うことができます。オブジェクトは、これらの変数を持っている場合、これは何をするか

class Event 
    def method_missing(method_name, *args, &block) 
    if instance_variable_names.include? "@#{method_name}" 
     instance_variable_get "@#{method_name}" 
    else 
     super 
    end 
    end 
end 

は、アクセスがobject.variable構文でインスタンス変数をオブジェクトを許可していますattr_accessorを介してクラス全体を変更することなく、定義することができます。

関連する問題