Quick tip 5: Using partials
Internal navigation bar
At this point, our Cases Index page looks like this:
And the New Case page looks like this:
What if we want to add the navigation bar here as well? Should we copy and paste all the code? Fortunately, no.
One of the core principles of Rails is DRY - Don't Repeat Yourself. Rails has several mechanisms to help us not repeat ourselves. One of them is called partials.
Simply put, partials are small pieces of HTML (or ERB) code that can be included at any place in our code. Let's create a partial for the navbar and then use it on other pages.
Create a new directory under
shared. (The name of the directory is not very important, as long as we're consistent with the way we refer to it).
In this directory, create a file called
_internal_navbar.html.erb. The underscore is important, it will tell Rails that this is not a regular view, but a partial one.
I am also using
internalto distinguish the navbar displayed on the pages seen by authenticated and non-authenticated users, to anticipate future problems.
Now go to the file
app/views/cases/index.html.erb, take the first part (starting from
<nav class="navbar navbar-default">, ending at
</nav>) cut it and paste it into the newly created
We have just created a partial. Next, we need to tell our view to use this partial instead of the old code. Open
app/views/cases/index.html.erb and add the following at its top:
<%= render "shared/internal_navbar" %>
This will tell Rails to render the newly created partial (that stays in
When we save the file, and refresh the Case Index browser page, it looks just like before:
Except now we have reusable code we can insert in other views, too.
app/views/cases/new.html.erb file and add at the top of the file:
<%= render "shared/internal_navbar" %>
Save the file and go to the New Case page. You will see the navbar:
Do the same for the
app/views/cases/edit.html.erbfile. If you want to have the navbar on other internal pages we will create, don't forget to add the
<%= render "shared/internal_navbar" %>line of code at the top.
One more thing, though. When you are on the New Case page and try to follow the "Case management system" link, you will get nothing. If you look at the code in the
views/shared/_internal_navbar.html.erb partial, you will see:
<div class="navbar-header"> <a class="navbar-brand" href="#">Case management system</a> </div>
We would like this link to take us to the root path instead (that we defined to be the Cases Index page), so we will use the
link_to helper. Change the code above to:
<div class="navbar-header"> <%=link_to("Case management system", root_path, class: "navbar-brand") %> </div>
External navigation bar
Let's do the same thing for the external pages - those seen by the users who are not authenticated on the platform.
Create a new file,
views/pages/landing.html.erb file, cut and paste the section between the
<nav ...> and
</nav> tags into the
views/shared/_external_navbar.html.erb file (and save):
views/pages/landing.html.erb file, add the following line instead of the previous block:
<%= render "shared/external_navbar" %>
Do the same for the other pages, in
views/devise/sessions/new.html.erb. Save the files and refresh the corresponding pages to check the addition of the navbar.
However, when I look at the code in
views/shared/_external_navbar.html.erb, I have to admit that it uses more classes and functionality that we understand and need right now.
Moreover, the collapsible elements are a headache and they do not work, since we did not add all the theme components.
This is why I chose not to bother and replaced the whole thing in
views/shared/_external_navbar.html.erb with something simpler and shorter, an adaptation of the internal navbar:
<nav class="navbar navbar-default", style="margin-bottom: 0"> <div class="container-fluid"> <div class="navbar-header"> <%=link_to("Case management system", root_path, class: "navbar-brand topnav") %> </div> <div class="navbar-collapse"> <ul class="nav navbar-nav navbar-right"> <li> <%= link_to("Features", features_path) %> </li> <li> <%= link_to("Register now", new_user_registration_path)%> </li> <li> <%= link_to("Sign in", new_user_session_path)%> </li> </ul> </div> </div> </nav>
You don't need to do the same, if you choose to preserve your version, there are two things of which you should take note:
Making every page's home button take the users to the root path was ensured by replacing the
<a href=#> ... </a>with:
<div class="navbar-header"> <%=link_to("Case management system", root_path, class: "navbar-brand topnav") %> </div>
The style addition in
<nav class="navbar navbar-default", style="margin-bottom: 0">overrides a behavior requesting body padding. Try to the
style="margin-bottom: 0"part and see how it influences the landing page.