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.