The partials in Ruby on Rails can quickly become a nightmare to manage because the only way to have the list of variables (locals in Rails jargon) used by a partial is to directly read its source code, which often contains several hundred lines of HTML code…
Since the release of Ruby on Rails 7.1, it is possible to use magic comments at the top of your partials to constrain and document the use of locals in that partial.
Let’s see right away how this works. 👏
Let’s start by defining the partial’s variables as follows:
# app/views/users/_user_card.html.erb
<%# locals: (name:, email:) -%>
My name is <%= name %>
Reach me at <%= email %>
Then, we pass these variables from the template in the locals
hash.
# app/views/users/show.html.erb
<%= render partial: "user_card",
locals: {
name: @user.name.full,
email: @user.email
}
%>
As defined, the variables name
and email
are mandatory, and their absence will cause an error.
Let’s remove the email variable to see what happens.
# app/views/users/show.html.erb
<%= render partial: "user_card",
locals: {
name: @user.name.full
}
%>
An error is immediately raised.
ActionView::Template::Error (missing local: :email):
app/views/users/show.html.erb:1
Now, let’s try to pass an undefined variable.
# app/views/users/show.html.erb
<%= render partial: "user_card",
locals: {
name: @user.name.full,
email: @user.email,
phones: @user.phones
}
%>
A new error is raised, this time to tell us that this variable is not accepted because it was not declared in the partial.
ActionView::Template::Error (unknown local: :phones):
app/views/users/show.html.erb:1
Thanks to these two errors, we are now certain of the variables accepted by our partial and we have at the same time gained a bit of documentation! 🎉
Default Values
It is possible to give default values to variables, which will allow us not to have to pass them each time we render.
# app/views/users/_user_card.html.erb
<%# locals: (name:, email:, phones: []) -%>
My name is <%= name %>
Reach me at <%= email %>
You can also give me a call at <%= phones.join(", ") %>
This way, it is possible not to provide the phones
variable to the partial without the call to the join
method failing, because it has been called on nil
.
Disabling Variables
If you do not want any variables to be passed to your partial, this is also possible!
# app/views/users/_user_card.html.erb
<%# locals: () -%>
My name is John
Reach me at john@doe.com
You can also give me a call at 0123456789
If we attempt to pass variables during rendering, the error below will be raised.
ActionView::Template::Error (no locals accepted):
app/views/users/show.html.erb:1
That concludes our little tour of this new feature in Rails 7.1, allowing us to exercise better control over the variables passed to our partials while documenting them.