В Rails 3 как визуализировать HTML в ответ JSON?
Я переношу приложение из Merb 1.1/1.8.7 в Rails 3 (бета)/1.9.1, которое использует ответы JSON, содержащие фрагменты HTML, например контейнер JSON, определяющий обновление, в записи пользователя и обновленная строка пользователя выглядит. В Merb, так как любой метод контроллера возвращается клиенту, можно скомпоновать Hash, назначить обработанное частичное к одному из ключей и вернуть hash.to_json (хотя это, конечно, может быть не лучшим образом.) В Rails, кажется, что для возврата данных к клиенту нужно использовать render, а render можно вызывать только один раз, поэтому рендеринг хеша json не будет работать из-за частичного рендеринга.
Из чтения, кажется, можно помещать эти данные в файл представления JSON.erb, причем <% = render partial% > in и визуализировать это. Есть ли Rails-способ решения этой проблемы (вернуть JSON, содержащий один или несколько фрагментов HTML), кроме этого?
В Merb:
Контроллер:
only_provides :json
...
self.status = 204 # or appropriate if not async
return {
'action' => 'update',
'type' => 'user',
'id' => @user.id,
'html' => partial('user_row', format: :html, user: @user)
}.to_json
В Rails:
Контроллер:
respond_to do |format|
format.json do
render template: '/json/message-1',
locals: {
action: 'update',
type: 'user',
id: @user.id,
partial: 'user_row.html.erb',
locals: { user: @user }
}
end
end
view: json/message-1.json.erb
{
"action": <%= raw action.to_json %>,
"type": <%= raw type.to_json %>,
"id": <%= raw id.to_json %>,
"html": <%= raw render(partial: partial, locals: locals).to_json %>
}
Ответы
Ответ 1
Ближайший к оригиналу подход Merb, который я мог найти в Rails, заключается в использовании # render_to_string
render json: {
'action' => 'update',
'type' => 'user',
'id' => @user.id,
'html' => render_to_string(partial: 'user_row.html.erb', locals: { user: @user })
}
Это связано с некоторой сложностью, возникающей при добавлении слоя шаблона json.erb в микс, независимо от того, какой подход Rails Purist я не мог сказать; возможно, что-то с RJS будет обычно использоваться.
Ответ 2
Еще один вопрос, который содержит больше решений для файлов json.erb. См. json erb template не может найти другие части html
Ответ 3
class UsersController < ApplicationController
respond_to :json
def show
@user = User.find(params[:id])
respond_with(@user) do |format|
if @user.save
format.json { render :json => @user }
else
format.json { render :json => @user.errors, :status => :unprocessable_entity }
end
end
end
end