2012-09-06 12 views
5

Używam Struct w odróżnieniu od prostego skrótu w projekcie, aby zapewnić semantyczną nazwę kolekcji par klucz-wartość. Jednak po zbudowaniu struktury muszę wygenerować wartość skrótu. Jestem w Rubim 1.9.3. Przykład:Elegancki sposób dodawania metody to_hash (lub to_h) do Struct?

MyMeaninfulName = Struct.new(:alpha, :beta, :gamma) do 
    def to_hash 
    self.members.inject({}) {|h,m| h[m] = self[m]; h} 
    end 
end 

my_var = MyMeaningfulName.new 
my_var.to_hash # -> { :alpha=>nil, :beta=>nil, :gamma=>nil } 

Czy istnieje powód, dla którego Struct nie zawiera metody to_hash? Wydaje się to być naturalne dopasowanie, ale być może istnieje przyczyna, dla której nie jest uwzględnione.

Po drugie, czy istnieje bardziej elegancki sposób na zbudowanie ogólnej metody to_hash w Struct (ogólnie, za pomocą makrowania lub poprzez moduł lub dziedziczenie).

+0

Aby wyjaśnić drugą część pytania ... Ponieważ Struct jest fabryką klas, nie jestem pewien, jak dodać funkcjonalność to_hash (co byłoby łatwe w każdej tradycyjnej klasie). – GSP

+0

Jeśli chcesz wyjaśnić, możesz edytować pytanie - po prostu kliknij link ** edit ** pod tekstem pytania. Przy okazji, dobre pytanie. +1! – Linuxios

Odpowiedz

0

Spróbuj tego:

class Struct 
    old_new = self.method(:new) 
    def self.new(*args) 
    obj = old_new.call(*args) 
    obj.class_exec do 
     def to_hash 
     self.members.inject({}) {|h,m| h[m] = self[m]; h} 
     end 
    end 
    return obj 
    end 
end 
+0

Otrzymuję 'nieokreśloną zmienną lokalną lub metodę old_new' dla Struct: Class', gdy próbuję:' class MyClass

2

czy to:

class Struct 
    def to_hash 
    self.class.members.inject({}) {|h,m| h[m] = self[m]} 
    end 
end 

(zwróć uwagę na dodatkową klasę dostać się do członków)

+0

Wierzę, że w twoim bloku iniekcyjnym brakuje' h' jako wartości zwracanej; to rodzi dla mnie wyjątek. Lub użyj 'each' i przenieś' h' do zewnętrznego zakresu. – waldrumpus

+0

Jestem rozdarty między tą odpowiedzią a Linuxios. Jego jest bardziej rozwlekły, ale dla mnie bardziej precyzyjnie o tym, co się dzieje. – GSP

+0

@waldrumpus - kod działa mi ładnie - jak dziwnie się zgodził – froderik

2

nie wiem dlaczego, to wydaje się oczywiste, . Na szczęście można go używać jako hasha w wielu miejscach, ponieważ implementuje operatorów nawiasów.

W każdym razie, jest to dość elegancki:

MyMeaningfulName = Struct.new :alpha, :beta, :gamma do 
    def to_hash 
    Hash[members.zip values] 
    end 
end 

my_var = MyMeaningfulName.new 1, 2, 3 
my_var.to_hash # => {:alpha=>1, :beta=>2, :gamma=>3} 
3

Wiem, że pytanie jest o Ruby 1.9.3, ale wychodząc z Ruby 2.0.0, Struct ma to_h metodę, która spełnia swoje zadanie.

MyMeaningfulName = Struct.new(:alpha, :beta, :gamma) 

my_var = MyMeaningfulName.new 
my_var.to_h # -> { :alpha=>nil, :beta=>nil, :gamma=>nil } 
MyMeaningfulName = Struct.new(:alpha, :beta, :gamma) 

my_var = MyMeaningfulName.new 
my_var.to_h # -> { :alpha=>nil, :beta=>nil, :gamma=>nil } 
Powiązane problemy