2010-03-23 12 views
9

Próbuję przekonwertować model ActiveRecord na JSON w Railsach, a podczas gdy metoda to_json ogólnie działa, wirtualne atrybuty modelu nie są uwzględniane. Czy istnieje sposób wewnątrz Railsów do wyświetlania nie tylko atrybutów modelu, ale także atrybutów attr_accessor i attr_reader, aby wszystkie czytelne atrybuty były dostępne, gdy model jest konwertowany na JSON?Włączając wirtualne atrybuty modelu podczas konwertowania rekordu do JSON w Railsach

Odpowiedz

12

Przed Rails 3, użyj opcję: metoda:

@model.to_json(:method => %w(some_virtual_attribute another_virtual_attribute)) 

W Rails 3, użyj : metody opcja

@model.to_json(:methods => %w(some_virtual_attribute another_virtual_attribute)) 
+0

Działa to dla mnie, ale wtedy nie mogę filtrować atrybuty używając ': only => [: attr1,: attr2 ] '. Czy istnieje sposób na połączenie ': only' z parametrem': methods'? – Besi

+1

'to_json (only: [: key_a,: key_b], methods: [: method_name])' –

1

Nie jestem pewien, czy to zmieniło w Rails 3, ale teraz musisz użyć opcji: methods zamiast: method

14

Zrobiłem to, aby umieścić informacje chniczne w modelu i zachować metodę kompatybilny z żadnym innym klasa może to nazwać (as_json jest wywoływana przez to_json i ma zwrócić Hash):

class MyModel < ActiveRecord::Base 
    def as_json options=nil 
    options ||= {} 
    options[:methods] = ((options[:methods] || []) + [:my, :virtual, :attrs]) 
    super options 
    end 
end 

(testowane w szynach v3.0)

+0

+1: To działało ładnie i podoba mi się pomysł zdefiniowania tego raz w mojej klasie modelu – Besi

+0

+1: Najbardziej elegancki. Dziękuję Ci. –

+0

Naprawdę podobało mi się to rozwiązanie, bardzo eleganckie ... rzeczywiście! Najlepszą częścią tego jest to, że wskoczył on do ActiveAdmin bez żadnych problemów, kontrolery są abstrakcyjne i dynamicznie generowane, więc było to z pewnością najkrótsze rozwiązanie. – ARun32

0

Inne odpowiedzi odnoszą się do wywołania methods, które zwraca wszystkie metody, w tym te, które nie są atrybutami. Alternatywnym podejściem byłoby użycie attributes, która zwraca atrybuty modelu, z tym wyjątkiem, że nie zawiera jego atrybutów wirtualnych.

Jeżeli te są znane, a następnie dodając coś jak poniżej do modelu może pomóc:

VIRTUAL_ATTRIBUTES = %i{foo bar baz} 
VIRTUAL_ATTRIBUTES.each { |a| attr_accessor a } # create accessors 
def attributes 
    VIRTUAL_ATTRIBUTES.each_with_object(super) { |a,h| h[a] = self.send(a) } 
end 
Powiązane problemy