I've been a bad kid and used the following syntax in my partial templates to set default values for local variables if a value wasn't explicitly defined in the :locals hash when rendering the partial --
<% foo = default_value unless (defined? foo) %>
This seemed to work fine until recently, when (for no reason I could discern) non-passed variables started behaving as if they had been defined to nil (rather than undefined).
As has been pointed by various helpful people on SO, http://api.rubyonrails.org/classes/ActionView/Base.html says not to use
defined? foo
and instead to use
local_assigns.has_key? :foo
I'm trying to amend my ways, but that means changing a lot of templates.
Can/should I just charge ahead and make this change in all the templates? Is there any trickiness I need to watch for? How diligently do I need to test each one?
introduced a nice feature called strict_locals
, it allows us to explicitly tell which locales are accepted in a partial.
Put this magic comment on top of your file:
<%# locals: (title: "Default title", subtitle: nil, other_required_param:) %>
This way, Rails will raise an ArgumentError, missing local: :other_required_arg
when not given the parameter.
See the docs.
If you need to use the generated helpers in a partial that is rendered as a collection of items, remember to put it on top of the file.
For instance:
_product.html.erb
<%# locals: (product_iteration:, product_counter:) %>
Collection size: <%= product_iteration.size %>
Item index: <%= product_counter %>