euisblue
[RoR] How to use partial template
Learn how to create partials with local variables  

Partial Template

We have two files: a.html.erb and b.html.erb, with similar contents.

a.html.erb

1<div class="container mx-auto"> 2 <h1> a.html.erb </h1> 3 4 <ul role="list"> 5 <li>Ruby</li> 6 <li>Rails</li> 7 <li>C++</li> 8 <li>C</li> 9 <li>Python</li> 10 <li>JavaScript</li> 11 ... 12 ... 13 <!-- many more --> 14 </ul> 15</div>

b.html.erb

1<div class="container mx-auto"> 2 <h1> b.html.erb </h1> 3 4 <ul role="list"> 5 <li>Ruby</li> 6 <li>Rails</li> 7 <li>C++</li> 8 <li>C</li> 9 <li>Python</li> 10 <li>JavaScript</li> 11 ... 12 ... 13 <!-- many more --> 14 </ul> 15</div>

Contents of both files are identical except <h1> tag. I'm going to follow the DRY (Don't Repeat Yourself) principle and remove those duplicates using a partial template.

Creating a partial

The name of the partial template or a partial starts with an underscore(_).

Here's my partial _langList.html.erb:

1<ul role="list"> 2 <li>Ruby</li> 3 <li>Rails</li> 4 <li>C++</li> 5 <li>C</li> 6 <li>Python</li> 7 <li>JavaScript</li> 8 ... 9 ... 10 <!-- many more --> 11</ul>

Now we can replace these codes in a.html.erb and b.html.erb with the partial we just created.

Calling a partial

a.html.erb

1<div class="container mx-auto"> 2 <h1> a.html.erb </h1> 3 4 <%= render partial: 'langList' %> 5</div>

b.html.erb

1<div class="container mx-auto"> 2 <h1> b.html.erb </h1> 3 4 <%= render partial: 'langList' %> 5</div>

Note that I didn't use '_langList'. You don't need to include the underscore when passing the name. In fact, you shouldn't include it otherwise rails wont be able to locate partials.

Sometimes you might need to specify the partial in a specific view directory. Let say you have a _langList.html.erb inside the home view.

1<%= render partial: 'home/langList' %>

Passing local variables

We can further reduce those codes in a.html.erb and b.html.erb by passing in contents inside the <h1> tag with a variable to the partial.

a.html.erb

1<div class="container mx-auto"> 2 <%= render partial: 'langList', :locals => {:title => "a.html.erb"} %> 3</div>

b.html.erb

1<div class="container mx-auto"> 2 <%= render partial: 'langList', :locals => {:title => "b.html.erb"} %> 3</div>

Using :locals, we can pass in variables to the partial. Here, :title is the key I named, and I can access its value with title (without the colon) in partial.

_langList.html.erb

1<h1> <%= title %> </h1> 2 3<ul role="list"> 4 <li>Ruby</li> 5 <li>Rails</li> 6 <li>C++</li> 7 <li>C</li> 8 <li>Python</li> 9 <li>JavaScript</li> 10 ... 11 ... 12 <!-- many more --> 13</ul>

If you want, you can even include those <div> tags inside the partial and reduce the code even further more.

_langList.html.erb

1<div class="container mx-auto"> 2 <h1> <%= title %> </h1> 3 4 <ul role="list"> 5 <li>Ruby</li> 6 <li>Rails</li> 7 <li>C++</li> 8 <li>C</li> 9 <li>Python</li> 10 <li>JavaScript</li> 11 ... 12 ... 13 <!-- many more --> 14 </ul> 15</div>

a.html.erb

1<%= render partial: 'langList', :locals => {:title => "a.html.erb"} %>

b.html.erb

1<%= render partial: 'langList', :locals => {:title => "b.html.erb"} %>

Reference