Во-первых, желаемый результат
У меня есть модели User
и Item
. Я хотел бы создать ответ JSON, который выглядит так:
{
"user":
{"username":"Bob!","foo":"whatever","bar":"hello!"},
"items": [
{"id":1, "name":"one", "zim":"planet", "gir":"earth"},
{"id":2, "name":"two", "zim":"planet", "gir":"mars"}
]
}
Однако моя модель User
и Item
имеет больше атрибутов, чем только те. Я нашел способ заставить это работать, но остерегаться, это не очень... Пожалуйста, помогите...
Update
Следующий раздел содержит исходный вопрос. В последнем разделе показано новое решение.
Мои хаки
home_controller.rb
class HomeController < ApplicationController
def observe
respond_to do |format|
format.js { render :json => Observation.new(current_user, @items).to_json }
end
end
end
observation.rb
# NOTE: this is not a subclass of ActiveRecord::Base
# this class just serves as a container to aggregate all "observable" objects
class Observation
attr_accessor :user, :items
def initialize(user, items)
self.user = user
self.items = items
end
# The JSON needs to be decoded before it sent to the `to_json` method in the home_controller otherwise the JSON will be escaped...
# What a mess!
def to_json
{
:user => ActiveSupport::JSON.decode(user.to_json(:only => :username, :methods => [:foo, :bar])),
:items => ActiveSupport::JSON.decode(auctions.to_json(:only => [:id, :name], :methods => [:zim, :gir]))
}
end
end
Посмотри Ма! Больше никаких хаков!
Вместо as_json
вместо
ActiveRecord:: Serialization # as_json Документы довольно скудны. Здесь кратко:
as_json(options = nil)
[show source]
Для получения дополнительной информации о to_json
vs as_json
см. принятый ответ для Переопределение to_json в Rails 2.3.5
Код без хаков
user.rb
class User < ActiveRecord::Base
def as_json(options)
options = { :only => [:username], :methods => [:foo, :bar] }.merge(options)
super(options)
end
end
item.rb
class Item < ActiveRecord::Base
def as_json(options)
options = { :only => [:id, name], :methods => [:zim, :gir] }.merge(options)
super(options)
end
end
home_controller.rb
class HomeController < ApplicationController
def observe
@items = Items.find(...)
respond_to do |format|
format.js do
render :json => {
:user => current_user || {},
:items => @items
}
end
end
end
end