Deekor
Deekor

Reputation: 9499

Rails 5 render set instance variables in locals

I have some complicated PDF generation logic that requires rendering a view outside of a controller and then passing the HTML into 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}

This all works fine on Rails 4 but has stopped working when we upgraded to Rails 5.

All the instance variables we are setting here end up as nil inside the view. Is there still a way to set instance variables from the render call like this?

Upvotes: 7

Views: 3794

Answers (2)

coreyward
coreyward

Reputation: 80060

Rails 5 introduced ActionController::Base.render, which allows you to do this instead:

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
  }
)

Which you can then pass to 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.

Upvotes: 13

Deekor
Deekor

Reputation: 9499

ActionView::Base has a method assign which can be called to set the instance variables.

    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'

Upvotes: 3

Related Questions