Ruby on Rails Advanced JSON Serialization
Я ищу, чтобы сделать индекс всех статей вместе с полной статьей через JSON в моем приложении rails, но я немного затрудняюсь выяснить, как это сделать.
Вот мой контроллер сейчас:
if params[:id]
@article = Article.find(params[:id])
else
@article = Article.published.not_draft.by_recent.first
end
respond_to do |format|
format.js { render :json => @article.to_json(
:except => [ :created_at, :updated_at, :draft, :id, :publish ],
:include => {
:comments => {
:only => [:body]
}
}),
:callback => params[:callback]}
end
Что бы я хотел сделать в ответ, добавьте индекс всех статей, например:
@index = Article.find(:all, :select => 'id, title')
Единственный способ, которым я смог это сделать, - поместить индекс и статью в хэш или массив, а затем поместить это в JSON.
@response = { :item => @article, :index => @index }
Полный код с обоими:
@index = Article.find(:all, :select => 'id, title')
if params[:id]
@article = Article.find(params[:id])
else
@article = Article.published.not_draft.by_recent.first
end
@response = { :item => @article, :index => @index }
respond_to do |format|
format.js { render :json => @response.to_json(), :callback => params[:callback]}
end
Это было бы хорошо, но теперь я не могу указать :include
или :except
и получить его для правильного отображения.
Ответы
Ответ 1
Вы намекаете на решение в своем вопросе. Скорее всего, вы хотите создать хэш для рендеринга JSON. Предпочтительный способ сделать это сейчас - обеспечить реализацию метода as_json. as_json предоставляет формальные средства настройки вывода to_json путем создания хэша, содержащего данные, которые вы хотите кодировать.
Более тщательное рассмотрение того, как взаимодействовать as_json и to_json, можно найти на веб-сайте Джонатана Джулиана.
Ответ 2
Просто, чтобы быть понятным, код выше работает с: include и: except. И по работам я имею в виду, что это не вызывает ошибки. Проблема состоит в том, что он включает комментарии для каждой статьи в индексе. Я просто хочу включить комментарии для: item, а не из статей, перечисленных в индексе.
Я не мог заставить вложенность работать как хэш или объект OpenStruct.
Вложение включено: включает в себя ошибку, вложенность: исключение не выдает ошибку, но ничего не отфильтровывается: created_at и т.д. все еще отображаются.
...
@response = { :item => @article, :index => @index }
format.js { render :json => @response.to_json(
:except => {:item => [ :created_at, :updated_at, :draft, :id, :publish ]},
:include => { :item => {
:comments => {
:only => [:body]
}
}}),
:callback => params[:callback]}
end
Ответ 3
Вы должны иметь возможность вставлять :include
, :except
и т.д. так:
:except => {:item => [ :created_at, :updated_at, :draft, :id, :publish ]}...
Если это не работает, сделайте его объектом (например, OpenStruct) вместо хеша.
- Маркус
Ответ 4
to_json имеет параметр метода: method, который включает результат любого имени метода, вы можете определить метод на этой модели, который возвращает дополнительные данные, которые вы хотите в своем JSON.
Ответ 5
(Примите ответ)
Я думаю, что ссылка, которую дал нирвдрум, содержит ваш ответ. Я отвечаю только потому, что никто не упомянул encode_json
.
В вашем случае вы должны иметь дело только с as_json
. Либо создавая хеш (с различными вызовами as_json
), и отправляя его на render :json => ...
(без вызова to_json
), либо просто реализуя as_json
на вашей модели и позволяя рельсам выполнять всю работу. (Но я подозреваю, что вам понадобится первая.)
Если вам действительно нужны какие-то причудливые js в вашем рендерированном ответе, вы можете реализовать encode_json
в своих классах (опять же, не to_json
). Например:
class JsEmptyClosure
def encode_json(*args)
"jQuery[\"noop\"] || function(){}"
end
def as_json(*args) self end
end
Теперь ответ будет отвечать to_json
на допустимые js (но обратите внимание, что это не json).
Ответ 6
Спасибо за вопрос, я могу настроить свой json-формат для модели с несколькими ассоциациями.
сделать json: @posts.to_json (
: except = > [: created_at,: updated_at,: user_id],
: include = > {
: user = > {: only = > [: email,: phone]},
: location = > {: only = > [: title,: lat,: lon,: street,: city,: state,: Почтовый индекс]},
: uploads = > {: only = > [: image]}
}
)
Ответ 7
Я бы рекомендовал перегрузить метод атрибутов для возврата альтернативного хеша, который будет автоматически использоваться для вывода to_json.
class Article
def attributes
{ ... } # define your hash that you want to return at the '...'
end
end
Мне кажется, что это намного проще, чем прямо с to_json.