如何将erb模板渲染为字符串内部动作?

时间:2013-01-16 02:59:14

标签: ruby-on-rails ruby-on-rails-3

我需要一串html(类似"<html><body>Hello World</body></html>")来传真。

我把它写成了一个单独的erb文件:views/orders/_fax.html.erb, 并尝试渲染erb:html_data = render(:partial => 'fax')

以下是引发问题的控制器的一部分:

  respond_to do |format|
      if @order.save   
        html_data = render(:partial => 'fax')
        response = fax_machine.send_fax(html_data)
        ......

        format.html { redirect_to @order, notice: 'Order was successfully created.' }
        format.json { render json: @order, status: :created, location: @order }
      else  
        format.html { render action: "new" }
        format.json { render json: @order.errors, status: :unprocessable_entity }
      end
    end

它给了我一个AbstractController :: DoubleRenderError,如下所示:

AbstractController::DoubleRenderError in OrdersController#create

Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like "redirect_to(...) and return".

如何解决这个问题?

4 个答案:

答案 0 :(得分:16)

如果您只需要渲染的HTML,并且不需要控制器的任何功能,您可以尝试直接在辅助类中使用ERB,例如:

module FaxHelper

  def to_fax
    html = File.open(path_to_template).read
    template = ERB.new(html)
    template.result
  end

end

ERB docs更详细地解释了这一点。

修改

要从控制器获取实例变量,请将绑定传递给result调用,例如:

# controller
to_fax(binding)

# helper class
def to_fax(controller_binding)
  html = File.open(path_to_template).read
  template = ERB.new(html)
  template.result(controller_binding)
end

注意:我从未这样做过,但似乎可行:)

答案 1 :(得分:6)

使用#render_to_string方法

它的工作方式与典型的渲染方法相同,但在需要将一些模板化的HTML添加到json响应时非常有用

http://apidock.com/rails/ActionController/Base/render_to_string

答案 2 :(得分:0)

如果您不想转义html,只需在其上调用.html_safe:

"<html><body>Hello World</body></html>".html_safe

重新发送错误,请发布您的OrdersController - 看起来您在创建操作中多次调用渲染或重定向。

(顺便说一句,以防万一你正在尝试它 - 你不能在控制器中渲染部分 - 你只能渲染视图中的部分)

编辑:是的,你的问题是你试图在控制器动作中渲染部分。您可以使用after_create回调来设置和发送传真 - 尽管您再也不想使用部分(因为它们用于视图)。 http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html

编辑:对于你的传真问题,你可以创建一个普通的Ruby类,看看Yehuda提出的这些建议:https://stackoverflow.com/a/1071510/468009

答案 3 :(得分:0)

原因是您无法在给定时间内多次在同一个动作中渲染或重定向。

但在您的代码中,您同时拥有renderredirect。我认为在你的控制器中你可以只使用渲染,假设你不需要任何json输出。

试试这个

def create
  @order.save   
  render(:partial => 'fax')
end

我没有对此进行过测试,但我猜你得到了这个想法:),并考虑一种处理错误的方法(如果订单没有保存的话)。