The following example is taken from Michael Hartl’s excellent Ruby On Rails Tutorial book. For the full example click here. I am reviewing it here for brevity and learning.

Say our rails application has three pages, all with the same base title, but one little bit of difference.

Page URL Base title Variable title
Home /pages/home “Ruby on Rails Tutorial Sample App” ” | Home”
Contact /pages/contact “Ruby on Rails Tutorial Sample App” ” | Contact”
About /pages/about “Ruby on Rails Tutorial Sample App” ” | About”


For example:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Ruby on Rails Tutorial Sample App | Home</title>
</head>
<body>
<h1>Sample App</h1>
<p>
This is the home page for the
<a href="http://www.railstutorial.org/">Ruby on Rails Tutorial</a>
sample application.
</p>
</body>
</html>

How could we refactor out the common base title, yet dynamically generate the one bit that is different in our view?

Here’s how you do it.

Step 1: Replace hard coding with instance variables.

To dynamically generate our content we are going to replace this:

<title>Ruby on Rails Tutorial Sample App | Home</title>

with this:

<title>Ruby on Rails Tutorial Sample App | <%= @title %></title>

In each of our three hard coded title pages.

The @title bit is a rails instance variable. And this is rails way saying: “This variable is going to be populated dynamically from the controller and it’s action commands.”

By defining an instance variable on our page we are now free to set the value of each page title in our controller and it’s corresponding action:

app/controllers/pages_controller.rb

class PagesController &lt; ApplicationController
   def home
      @title = "Home"
   end

   def contact
      @title = "Contact"
   end

   def about
      @title = "About"
   end
end

This will now dynamically replace @title with the proper variable depending on which page is rendered.

Now if generating dynamic content was all we wanted to do we’d be done.

But what if there was more duplication on our pages, and we wanted a way to factor that out into a common place. Rails gives us a way to do that with layouts.

Step 2: Eliminate duplication using layouts.

Say the structure of all of our pages looks something like this:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Ruby on Rails Tutorial Sample App | <%= @title %></title>
</head>
<body>
   Contents
</body>
</html>

Where ‘Contents’ is the bit that changes from page to page. To capture this common structure skeleton we can create an application.html.erb file and put our common layout code in there.

app/views/layouts/application.html.erb

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Ruby on Rails Tutorial Sample App | <%= @title %></title>
</head>
<body>
   <%= yield %>
</body>
</html>

Here all the magic happens in the line:

<%= yield %>

Basically the layout file is saying:

‘I will layout your page, substituting in any variables you set (like @title) but when I get to this yield bit, I am going to pass control over to you let your ‘view’ render whatever it wants.’

So our views now contain just the dynamic stuff specific to each view.

app/views/pages/home.html.erb

<h1>Sample App</h1>
<p>
This is the home page for the
<a href="http://www.railstutorial.org/">Ruby on Rails Tutorial</a>
sample application.
</p>

Here is what another view might render.

app/views/pages/contact.html.erb

<h1>Contact</h1>
<p>
Contact Ruby on Rails Tutorial about the sample app at the
<a href="http://www.railstutorial.org/feedback">feedback page</a>.
</p>

That’s it! You’ve can now dynamically use instance variables to set model information that gets passed to the page via the controller and the view, and you can now pull common layout into an application file to reduce duplication.

Again, for the (much better) fuller example be sure to check out Michael Hartl’s book.