As our view files get larger, we make use of partial templates to move some code to its own file. This also helps us to follow the single-responsibility principle. Partials also accept local variables, enhancing their flexibility and power.

Before Rails 7.1

Prior to Rails 7.1, we could not restrict which local variables we can pass to the partials.

Rails 7.1 onwards

Rails 7.1 adds the ability to define the local variables a template can accept. This helps in precompiling templates during application startup rather than at runtime. To achieve this, we have to add a locals magic comment inside the partial.

# app/views/dashboard/_contact_us.html.erb

<%# locals: (address:, mobile:) -%>

<%= address %>
<%= mobile %>

With the help of the magic comment, we have defined only two locals address & mobile. This can be passed to the partial as follows:

# app/views/homepage/index.html.erb

<%= render partial: 'contact_us', locals: { address: 'Mumbai', mobile: '987654321' } %>

Now, if we try to pass an additional local variable, let's say company

# app/views/homepage/index.html.erb

<%= render partial: 'contact_us', locals: { address: 'Mumbai', mobile: '987654321', company: 'Test Company' } %>

The above will throw the following error in the server log

ActionView::Template::Error (unknown local: :company):
  
app/views/homepage/index.html.erb:2

Also, if we define a local variable but do not pass it while rendering the partial, for instance, let's fail to pass the defined local variable mobile on rendering the partial

# app/views/homepage/index.html.erb

<%= render partial: 'contact_us', locals: { address: 'Mumbai' } %>

The server log will warn us with the following error

ActionView::Template::Error (missing local: :mobile):

app/views/homepage/index.html.erb:2

Passing default values

We can also pass a default value to the locals as follows:

# app/views/dashboard/_contact_us.html.erb

<%# locals: (address: 'Delhi', mobile: 1234567890) -%>

<%= address %>
<%= mobile %>

Now, if we missed out to pass the locals while rendering the template/partial, it will use the default value assigned by the magic comment.

Disabling locals

We can disable passing any locals to the partial. Add the following magic comment to the partial.

# app/views/dashboard/_contact_us.html.erb

<%# locals: () %>

<h1>Contact Us</h1>
<p>Mumbai</p>
<p>1234567890</p>

Now, if we try to pass locals while rendering the above partial, the server log will throw the below error.

ActionView::Template::Error (no locals accepted):
  
app/views/homepage/index.html.erb:2

References