Rails 5 个本地渲染集实例变量

Rails 5 render set instance variables in locals

我有一些复杂的 PDF 生成逻辑,需要在控制器外部渲染视图,然后将 HTML 传递到 WickedPDF:

ActionView::Base.send(:define_method, :protect_against_forgery?) { false }
av = ActionView::Base.new
av.view_paths = ActionController::Base.view_paths

income_statement_html = av.render :template => "reports/income_statement.pdf.erb", :layout => 'layouts/report.html.erb',
                                  locals: {:@revenue_accounts => revenue_accounts,
                                           :@expense_accounts => expense_accounts,
                                           :@start_date => start_date,
                                           :@end_date => end_date,
                                           :@business => business}

这在 Rails 4 上一切正常,但是当我们升级到 Rails 5 时就停止工作了。

我们在此处设置的所有实例变量最终在视图中显示为 nil。还有办法像这样从渲染调用中设置实例变量吗?

ActionView::Base 有一个方法 assign 可以调用它来设置实例变量。

    av.assign({revenue_accounts: revenue_accounts,
           expense_accounts: expense_accounts,
           start_date: start_date,
           end_date:  end_date,
           business: business})

income_statement_html = av.render :template => "reports/income_statement.pdf.erb", :layout => 'layouts/report.html.erb'

Rails 5 介绍了 ActionController::Base.render,它允许您改为这样做:

rendered_html = ApplicationController.render(
  template: 'reports/income_statement',
  layout: 'report',
  assigns: {
    revenue_accounts: revenue_accounts,
    expense_accounts: expense_accounts,
    start_date: start_date,
    end_date: end_date,
    business: business
  }
)

然后您可以将其传递给 WickedPDF:

WickedPdf.new.pdf_from_string(rendered_html)

You can read more about .render and using it with WickedPDF, as well get some examples of how to extract this functionality into reusable objects on this blog post.