2011-08-30 12 views
6

Wiem, jak wyłączyć element główny globalnie, a la Rails 3.1 include_root_in_json lub za pomocą ActiveRecord::Base.include_root_in_json = false, ale chcę to zrobić tylko dla kilku żądań JSON (nie globalnie).Railsy: Wyłącz root w JSON tylko dla określonych działań kontrolera?

tej pory robiłem to tak:

@donuts = Donut.where(:jelly => true) 
@coffees = Coffee.all 
@breakfast_sandwiches = Sandwich.where(:breakfast => true) 

dunkin_donuts_order = {} 
dunkin_donuts_order[:donuts] = @donuts 
dunkin_donuts_order[:libations] = @coffees 
dunkin_donuts_order[:non_donut_food] = @breakfast_sandwiches 

Donut.include_root_in_json = false 
Coffee.include_root_in_json = false 

render :json => dunkin_donuts_order 

Donut.include_root_in_json = true 
Coffee.include_root_in_json = true 

Istnieje około 5 przypadków, gdzie mam to zrobić, czasami więcej niż jednego modelu, a nie czuć w czystości wszystko. Próbowałem to wstawić w around_filter s, ale wyjątki zrywały przepływ i to też było owłosione.

Musi istnieć lepszy sposób!

+0

Nie odpowiada to bezpośrednio na twoje pytanie, ale odpowiada na pytanie, które tu przyszedłem: MOŻESZ tłumić root przy poszczególnych połączeniach z 'to_json', np. 'Donut.to_json (root: false)' – Lambart

Odpowiedz

2

Odpowiedź jest, niestety, tak i nie.

Tak, to, co zrobiłeś powyżej, można prawdopodobnie zrobić lepiej. Nie, Railsy nie pozwalają na dodanie korzenia na podstawie poszczególnych działań. Renderowanie JSON nie zostało zbudowane z myślą o takiej elastyczności.

Mając na uwadze powyższe, oto co zrobię:

  1. Set include_root_in_json do false dla tych modeli, które mają korzenie w zależności od działania (takie jak Donut i Coffee powyżej).
  2. Zastąpienie as_json, aby umożliwić większą elastyczność. Oto przykład:

    # in model.rb 
    def as_json(options = nil) 
        hash = serializable_hash(options) 
        if options && options[:root] 
         hash = { options[:root] => hash } 
        else 
         hash = hash 
        end 
    end 
    

    Ten przykład sprawi, że będzie można opcjonalnie przekazać katalog główny, ale domyślnie nie będzie to katalog główny. Można alternatywnie napisać to w inny sposób.

  3. Po przejęciu as_json trzeba odpowiednio zmodyfikować wywołania renderowania. Tak więc, dla Donut, zrobiłbyś render :json => @donut.to_json.

Mam nadzieję, że to pomoże!

+0

Dzięki. Przestałem strzelać sobie w stopach i przełączałem się na [RABL] (https://github.com/nesquena/rabl) i nigdy nie oglądałem się za siebie. O wiele lepiej! – neezer

+0

Dobra odpowiedź. ale nie musisz wywoływać as_json(). to_json, ponieważ to_json automatycznie nazywa twoje nadpisanie as_json. –

+0

Dzięki, @NadaAldahleh. Wyjaśniłem to nieco w mojej odpowiedzi. –

1

Można ustawić include_root_in_json od modelu instancji, a to nie będzie miało wpływu na klasę (patrz class_attribute w API szyn dla opisu tego zachowania). Możesz więc ustawić rozsądną wartość domyślną na poziomie klasy, a następnie ustawić inną wartość dla każdej instancji w odpowiednich kontrolerach.

przykład:

@donuts = Donut.where(:jelly => true).each {|d| d.include_root_in_json = false } 

Dla wygody, można tworzyć metodą narzędziowy, który przyjmuje tablicę wzorcowych przypadkach i ustawia wartość w każdym z nich.

Powiązane problemy