Как сделать представление нормально после использования render_to_string? - PullRequest
5 голосов
/ 13 января 2011

В моем приложении на Rails есть действие, которое создает документ XML с использованием шаблона шаблона XML Builder (rxml) и render_to_string.XML-документ пересылается на внутренний сервер.

После создания XML-документа я хочу отправить обычный HTML-ответ в браузер, но каким-то образом Rails вспоминает первый вызов render_to_string.

Например:

  • Rails не может найти представление по умолчанию show.html.erb, потому что оно ищет show.rxml.
  • Просто поместив render 'mycontroller/show.html.erb' в нижней части моего действияОбработчик заставляет Rails найти шаблон, но браузер не работает, потому что тип содержимого заголовка ответа text/xml.

Есть ли способ использовать render_to_string, не «портя» реальный браузерответ?

РЕДАКТИРОВАТЬ: Кажется, что в Rails 2 erase_render_results добился бы цели, но в Rails 3 он больше не доступен.

Ответы [ 3 ]

2 голосов
/ 14 января 2011

Прагматичный ответ заключается в том, что использование файла представления и двух вызовов для рендеринга - это не путь Rails: представления, как правило, отправляются клиенту, и ActionPack спроектирован таким образом.

Тем не менее, есть простой способ достичь того, что вы пытаетесь сделать. Вместо того, чтобы использовать ActionView, вы можете напрямую использовать Builder :: XmlMarkup для генерации XML в виде строки:

def action_in_controller
  buffer = ""
  xml = Builder::XmlMarkup.new(buffer)

  # build your XML - essentially copy your view.xml.builder file here 
  xml.element("value")
  xml.element("value")

  # send the contents of buffer to your 3rd server

  # allow your controller to render your view normally
end

Взгляните на документацию Builder , чтобы увидеть, как она работает.

Другая особенность Builder, которой вы можете воспользоваться, это то, что содержимое XML добавляется в буфер с помощью <<, поэтому можно использовать любой поток ввода-вывода. В зависимости от того, как вы отправляете контент на другой сервер, вы можете довольно просто обернуть его.

Конечно, это может оказаться очень запутанным и длинным, поэтому вы хотите инкапсулировать этот бит функциональности в другом классе или как метод в вашей модели.

2 голосов
/ 26 апреля 2011

При переносе гема actionwebservice я обнаружил ту же ошибку.В своем коде они обходят исключение двойного рендеринга, вызывая функцию erase_render_results.

Эта функция больше не доступна в rails3.К счастью, исправить это довольно легко (но мне потребовалось некоторое время, чтобы найти).

Внутри actionwebservice была вызвана следующая функция внутри контроллера, чтобы позволить второй рендер:

def reset_invocation_response
  erase_render_results
  response.instance_variable_set :@header, Rack::Utils::HeaderHash.new(::ActionController::Response::DEFAULT_HEADERS.merge("cookie" => []))
end

Чтобы сделатьэта работа в rails3, вам просто нужно написать:

def reset_invocation_response
  self.instance_variable_set(:@_response_body, nil)
  response.instance_variable_set :@header, Rack::Utils::HeaderHash.new("cookie" => [], 'Content-Type' => 'text/html')
end

Надеюсь, это поможет.

2 голосов
/ 14 января 2011

Похоже, что это может быть ошибкой в ​​рельсах 3 (по крайней мере, по сравнению с поведением 2.3.x render_to_string). В источнике для 2.3.8 они явно предпринимают дополнительные шаги для сброса content_type и устанавливают тело ответа равным nil (среди прочего).

def render_to_string
  ...
ensure
  response.content_type = nil
  erase_render_results
  reset_variables_added_to_assigns
end

но в источнике 3.0.3 для AbstractController :: Rendering

def render_to_string(*args, &block)
  options = _normalize_args(*args, &block)
  _normalize_options(options)
  render_to_body(options)
end

Вы видите, что явного сброса переменных нет, render_to_body просто возвращает view_context.render. Возможно, что контент-тип, response_body и т. Д. Обрабатываются в другом месте, и это красная сельдь, но мой первый инстинкт - установить

response.headers['Content-Type'] = 'text/html'

после вашего render_to_string до фактического рендеринга.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...