2011-09-23 21 views
18

Próbuję wygenerować attr_reader z hasha (z zagnieżdżonym hash), aby automatycznie odzwierciedlał tworzenie instancji instance_variable.Ruby: dynamicznie generuj attribute_accessor

tutaj jest to, co mam do tej pory:

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 

ale nie mogę znaleźć sposób, aby to zrobić :(

Odpowiedz

33

Trzeba wywołać (prywatny) klasy metody attr_accessor na Event klasa:

self.class.send(:attr_accessor, name) 

polecam dodać @ na tej linii:

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

I nie używaj ich w haszyszu.

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

Jesteś moim nowym najlepszym przyjacielem !!!! to po prostu działa i jest takie proste ... Ruby to magia :) a TY jesteś gwiazdą :) (jestem szczęśliwy, bo szukałem chwilę) –

+0

Po prostu szybkie pytanie więcej, czy jest jakikolwiek sposób na dodanie nazwy zawierający hasz zawierający nazwę elementu, aby mógłbym wywołać my_class.class.price lub coś w tym stylu? –

+0

Po pierwsze, "klasa" jest zastrzeżonym słowem kluczowym, nie należy jej używać. Twoje drugie pytanie w twoim komentarzu wykracza poza zakres tego konkretnego pytania. Możesz chcieć rozpocząć nowe pytanie, ponieważ dotyczy ono rekurencji i innych, nie z akcesoriami do atrybutów. (PS, nie zapomnij przyjąć najlepszej odpowiedzi) – rdvdijk

1

attr_accessor to metoda klasowa i jako taka musi być przywoływana na zajęciach. Jest to również metoda prywatna, więc należy ją wywołać w kontekście, w którym obiektem klasy jest self.

Jako przykład:

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

Po utworzeniu instancję C i wywołanie foo w tym przypadku, to wystąpienie - i wszystkie przyszłe przypadków - zawiera metody baz i baz=.

3

Można zrobić trochę meta-magii rozwiązać ten problem, używając 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 

Co to będzie zrobić, to umożliwić dostęp do obiektów zmiennych instancji poprzez składni object.variable, jeśli obiekt ma te zmienne zdefiniowane, bez uciekania się do modyfikacji całej klasy przez attr_accessor.

Powiązane problemy