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 app/views/
called 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
internal
to 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 app/views/shared/_internal_navbar.html.erb
:
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 shared/_internal_navbar
).
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.
Open the 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.erb
file. 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/shared/_external_navbar.html.erb
.
Open the 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):
In the 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/pages/features.html.erb
,views/devise/registrations/new.html.erb
,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 thestyle="margin-bottom: 0"
part and see how it influences the landing page.