2009-03-04 2 views
27

Я бы с удовольствием использовал render :json, но это кажется его не таким гибким. Каков правильный способ сделать это?render: json не принимает опции

respond_to do |format| 
    format.html # index.html.erb 
    format.xml { render :xml => @things } 

    #This is great 
    format.json { render :text => @things.to_json(:include => :photos) } 

    #This doesn't include photos 
    format.json { render :json => @things, :include => :photos } 
end 

ответ

39

Я сделал что-то подобное с render :json. Это то, что работает для меня:

respond_to do |format| 
    format.html # index.html.erb 
    format.json { render :json => @things.to_json(:include => { :photos => { :only => [:id, :url] } }) } 
end 
+0

Спасибо, это тоже помогло мне. – swilliams

+0

Помог мне. +1 – sscirrus

34

Я предполагаю, что эта статья может быть полезна для вас - Rails to_json or as_json? Джонатан Джулиан.

Основная мысль заключается в том, что вам следует избегать использования to_json в контроллерах. Гораздо более гибко определять метод as_json в вашей модели.

Например:

В модели Thing

def as_json(options={}) 
    super(:include => :photos) 
end 

И тогда вы можете написать в контроллере только

render :json => @things 
+0

это, вероятно, лучшее решение этой проблемы. – giosakti

+2

Можете сделать 'super (options.merge (: include =>: photos))', чтобы сохранить другие возможные параметры передачи. Вы все равно будете переопределять любые опции ': include', хотя ... логика для слияния значений для этого ключа будет немного более сложной. –

+0

Использование 'super options.reverse_merge: include =>: photos' позволит вам переопределить значение по умолчанию: include. (См. [Hash # reverse_merge] (http://api.rubyonrails.org/classes/Hash.html#method-i-reverse_merge)) – Steve

1

в случае массива, что я сделал это

respond_to do |format| 
    format.html 
    format.json {render :json => {:medias => @medias.to_json, :total => 13000, :time => 0.0001 }} 
end 
3

Управление сложными хэшами в ваших контроллерах становится ужасно быстрым.

С Rails 3 вы можете использовать ActiveModel :: Serializer. См. http://api.rubyonrails.org/classes/ActiveModel/Serialization.html

Если вы делаете что-то нетривиальное, см. https://github.com/rails-api/active_model_serializers. Я рекомендую создавать отдельные классы сериализаторов, чтобы избежать загромождения моделей и упростить тесты.

class ThingSerializer < ActiveModel::Serializer 
    has_many :photos 
    attributes :name, :whatever 
end 

# ThingsController 
def index 
    render :json => @things 
end 

# test it out 
thing = Thing.new :name => "bob" 
ThingSerializer.new(thing, nil).to_json 
Смежные вопросы