DEV Community

loading...
Cover image for An Overview: Templates, Layouts, & Partials - How Things Fit Together in Rails

An Overview: Templates, Layouts, & Partials - How Things Fit Together in Rails

saramccombs profile image Sara McCombs (she/her) ・5 min read
Photo by Gabriel Crismariu on Unsplash

The final HTML output of a Rails app relies upon three things working together in harmony: Templates, Layouts, and Partials.

Let's briefly review each.

Templates

So what is a template when it comes to Rails?

Template
/ˈtemplət/
noun
noun: template; plural noun: templates

Computing
a preset format for a document or file, used so that the format does not have to be recreated each time it is used.

Merriam-Webster to the rescue!

A Rails template is a visual format that provides for the consistent rendering of information while embracing DRY code principles.

View templates can be written in several ways, but we are usually accustomed to seeing them ending with the .erb extension.

Within an ERB template, a mixture of ERB (Embedded Ruby) and HTML are used to create the structure for the view. Ruby code can be included using both <%= %> (squid) and <% %> (ice cream cone) tags.

Note: "Squid" and "Ice cream cone" are not any official terminology (that I can find), but they are akin to "hash rocket" as they are a visual representation of these specific ruby tags.

"Ice cream cone" tags are used to execute Ruby code that does not return anything, such as conditional statements and loops.

"Squid" tags are used when you return data, such as when iterating over a collection.

Here's an example with both:

# app/views/index.html.erb

<h1>Star Trek Ships & Captains</h1>
<% @ships.each do |ship| %>
  <%= ship.name %> - Captain <%= ship.captain %>
<% end %>
Enter fullscreen mode Exit fullscreen mode

This loop is set up using the regular embedding "ice cream cone" tags while the ship and captain names are inserted using the output embedding "squid" tags.

Layouts

So what's a layout?

Layouts are used to render common view elements (header, navigations, footers, etc.) around view templates. These elements are all of the "bits" of a website that are persistent from one page to another.

Typically, a Rails app will have a couple of layouts that views are rendered within. The store checkout view might have different headers than the storefront. The create a new account view might have different navigation than the logout view. Different layouts allow us to embrace DRY code principles and reduce maintenance overhead when things change. Rather than having to change a header on every single view a web app contains, we only have one layout that needs to be updated.

Here's an example of a basic layout:

# app/views/layouts/application.html.erb

<html>
  <head>
  </head>
  <body>
  <%= yield %>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

Wait, what does <%= yield %> mean?

Within the context of a layout, <%= yield %> identifies a section where content from the view template should be inserted. The simplest way to use this is to have a single yield, into which the entire contents of the view currently being rendered is inserted. (Example above.)

But we can also have multiple yields within a layout:

# app/views/layouts/application.html.erb

<html>
  <head>
  <%= yield :head %>
  </head>
  <body>
  <%= yield %>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

The main body of the view template will always render into the unnamed yield while content rendered into a named yield, will respond to the content_for method within the view template.

# app/views/index.html.erb

<% content_for :head do %>
  <title>Star Trek - All Ships & Captains</title>
<% end %>

<h1>Star Trek Ships & Captains</h1>
<% @ships.each do |ship| %>
  <%= ship.name %> - Captain <%= ship.captain %>
<% end %>
Enter fullscreen mode Exit fullscreen mode

The content_for method is very helpful when your layout contains distinct regions such as sidebars and footers that should get their content inserted.

Partials

Ok.. So if a layout goes around a template, what is a partial?

A partial is another way to break apart the rendering process into many more manageable chunks. It allows us to move a section of repeated code into its own file. This ultimately helps to simplify our views and treats these partials as a "subroutine" that can be managed separately from the view that calls them. Again, embracing DRY code principles.

To render a partial as part of a view, we use the render method within the view:

<%= render "main_navigation" %>
Enter fullscreen mode Exit fullscreen mode

This will render a file named _main_navigation.html.erb, that resides within the view's directory, wherever in the view you called it with the render method.

We can also call partials in different directories utilizing the directory name. This will render a file named _menu.html.erb from the admin directory.

<%= render "admin/menu" %>
Enter fullscreen mode Exit fullscreen mode

What about a partial when we use local variables?

We can pass our render method a hash of local variables.

<%= render partial: "admin/menu", locals: {username: @user.username} %>
Enter fullscreen mode Exit fullscreen mode

The FIRST key/value partial: "admin/menu" tells Rails the name of the partial that you want to render.

The SECOND key/value pair specifies the local variables as a hash itself, locals: {username: @user.username}.

To make this partial use seamless, we need to ensure the local variable key (username in the above example) is the variable that we utilize within the partial itself.

What about a partial that we utilize within a layout?

It's similar to above:

<%= render partial: "link_area", layout: "graybar" %>
Enter fullscreen mode Exit fullscreen mode

This render method would look for a partial named _link_area.html.erb and render it utilizing the _graybar.html.erb layout.

Note: layouts for partials follow the same leading-underscoring naming convention as regular partials and are placed within the same folder as the partial that they belong to and *NOT in the master layouts folder.

Is this all you can do with partials?

Absolutely not. Checkout the Ruby Guide on Using Partials for the more in-depth partials examples.

Let's put it ALL together now

At it's simplest level, this is what happens when a request is made to your Rails app:

  1. Rails finds the view template for the corresponding action (new, index, edit, show) based either on naming convention or any other options passed to the render method within the controller action.

  2. Similarly, Rails then finds the correct layout to use. Again, either through naming/directory conventions or through specific options provided.

  3. Rails uses the action view template to generate the content specific to the action requested. The template might be composed of partials, which it will locate and generate the content specific to that partial.

  4. Rails then looks for the layout's <%= yield %> statement and inserts the action's view template (and any rendered partials) there.

This means that, for every request handled by Rails, at most one layout and action view template will be used. The action view template can also call out to other templates, called partials, to render itself.

Discussion (0)

pic
Editor guide