Passing optional locals to Rails partials
When passing locals to Rails partials, you might run into cases where you need to pass optional locals in some places, but don’t want to pass it in every other place where you use the partial.
As an example, you have a _post
partial
which you render like this:
<%= render 'post', post: post %>
And now you want to render the same partial from another view, but this time you want to pass a boolean flag to tell the partial to render the author bio as well.
<%= render 'post', post: post, show_author_bio: true %>
If we now used the show_author_bio
local in the partial,
it would break the other view
which does not know about this local.
To use it safely, we can make use of
the local_assigns
hash.
<h1><%= post.title %></h1>
<% if local_assigns[:show_author_bio] %>
<%= render 'author_bio', author: post.author %>
<% end %>
<%= post.body %>
Even though we’re using it for passing a boolean value here, we could pass in any other object as well. For instance, we could pass in an optional author object:
<% if local_assigns.has_key?(:author) %>
<%= render 'author_bio', author: author %>
<% end %>
Sadly, Rails documentation seems to be
missing details about this useful feature.
I'm not sure if this is because
it has been deprecated since Rails 4.
Do leave a comment below if you know why.
Update:
In earlier versions of Rails,
using defined?
did no work reliably in the views.
This is not the case in 4.2,
so the part of the ActionView::Base docs
that mentioned defined?
and local_assigns
was removed.
You can use defined?
like this:
<% if defined?(:author) %>
<%= render 'author_bio', author: author %>
<% end %>
local_assigns
is still available though,
and is still useful in cases
where you need to access the locals as a hash.
Update 2:
I went ahead and submitted a
pull request
adding documentation for local_assigns
.
There’s also another open issue for the same
(#15700)
that also added documentation.
Hopefully we will soon have documentation for local_assigns
.
DHH also opened an issue (#18962) about this yesterday, and had an interesting comment to make about this feature. ;-)
These f***ing Rails people have thought of everything!
local_assigns
is exactly this and already available.