I have a view that I'm rendering like this:
action_controller.render_to_string(
layout: 'document',
template: 'administrator/users/export',
encoding: 'UTF-8',
formats: [:pdf],
handlers: [:erb],
locals: {
testvar: "test"
}
)
And I'm trying to use this testvar variable in the specified document layout:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html class="document">
<head>
<title>
<%= "Test: #{testvar}" %>
</title>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width,initial-scale=1">
</head>
<body class="document pdf">
<%= yield %>
</body>
</html>
But I'm getting this exception:
*** NameError Exception: undefined local variable or method `testvar' for #ActionView::Base:0x000000000142f8
I also cannot get any instance variables in the layout.
How do I do this in Rails 7? This was possible to do in Rails 6.
The issue isn't really how you're passing the variables - it's how you're accessing them.
You can access locals through local_assigns
:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html class="document">
<head>
<title>
Test: <%= local_assigns[:testvar] %>
</title>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width,initial-scale=1">
</head>
<body class="document pdf">
<%= yield %>
</body>
</html>
But for some obscure reason the layout doesn't have access to the actual local variables like the view does. You can see this if you put a breakpoint in the layout:
(ruby) local_assigns
{:title=>"Hello World"}
(ruby) defined?(title)
nil
This suprising behavior is also documented in a stale issue.