【问题标题】:Rails 5 render set instance variables in localsRails 5 在本地渲染集合实例变量
【发布时间】:2017-01-30 21:14:24
【问题描述】:

我有一些复杂的 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 结尾。还有一种方法可以像这样从渲染调用中设置实例变量吗?

【问题讨论】:

  • :@revenue_accounts 看起来很奇怪...试试::revenue_accounts(在您的模板中,将它们称为局部变量,例如revenue_accounts,而不是更全局的@revenue_accounts)跨度>
  • @TarynEast 不会在视图中设置局部变量而不是实例变量吗?
  • 是的......这也应该有效。这个想法是您希望这些数据进入模板以便正确呈现吗?它是局部变量与实例变量的事实应该与最终目标无关?
  • @TarynEast 该模板用于依赖于实例变量的应用程序周围的其他事物。因此,对于这个 PDF,我试图通过重用模板并通过 locals 选项设置实例变量来编写 DRY 代码。
  • 您可以更改其他内容以也使用局部变量(在调用此模板的其他地方传入实例变量)...?

标签: ruby-on-rails ruby-on-rails-5 wicked-pdf


【解决方案1】:

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.

【讨论】:

    【解决方案2】:

    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'
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-11-13
      • 1970-01-01
      • 1970-01-01
      • 2014-10-31
      • 2020-04-18
      • 2013-03-24
      • 1970-01-01
      • 2015-10-22
      相关资源
      最近更新 更多