3.3. Creating HTML Dynamically with
erb

Do you know PHP (without any additional framework)? Then the content
of an erb file will seem very familiar to you. It is a
mixture of HTML and Ruby code (erb stands for
embedded
Ruby). But we cannot simply put such
an erb web page into the public
directory, as pages stored in this directory are delivered 1:1 without
first passing through an erb parser. This is the first
time for us to get in touch with the MVC model.[19] We need a controller and a view. We can create it via the command
rails generate controller. Let's have a look at the
help:

It's HTML, but for it to be a valid HTML page, something is
“missing” at the top and bottom (the missing HTML "rest" will
be explained in the section called “Layouts”). We launch the web server
to test it

Started GET "/example/test" for 127.0.0.1 at 2012-11-13 19:06:55 +0100
Connecting to database specified by database.yml
Processing by ExampleController#test as HTML
Rendered example/test.html.erb within layouts/application (2.7ms)

localhost (127.0.0.1) sent in an HTTP GET request
for the URI “/example/test”. That was then
apparently rendered as HTML by the controller
ExampleController using the method
test.

The other lines tell us that a bunch of CSS and JavaScript files are
compiled and than delivered.

Now we just need to find the controller. But you are in luck... I
know the answer. ;-) All controllers are in the directory
app/controllers, and there you go, we indeed find the
corresponding file
app/controllers/example_controller.rb.

That is very clear. The controller ExampleController is
a descendant of the ApplicationController and contains
currently just one method with the name test.
This method contains currently no program logic.

You will probably ask yourself how Rails knows that for the
URL path /example/test it should process the controller
ExampleController and the method test. This is
not determined by some magical logic, but by a routing configuration. You can find this in
the file config/routes.rb in the second line:

This line has been automatically inserted by the command
rails generate controller. In the routing file, you can
also carry out any mapping.
But more on this later. Currently, our routes look very simple. With the
command rake routes we can get them. The file contains
quite a few examples. But we'll dive into that later (Chapter 6, Routes). For now we have a look at the first two lines of that
file:

Yes, both the number 1 and the result of 1 + 1 is a
Fixnum. What happened? Rails is so intelligent
that it automatically calls all objects in a view (that is the file test.html.erb)
that are not already a string via the method .to_s, which always converts the
content of the object to a string (the section called “Method to_s for Your Own Classes”). Once
more, a brief trip to irb:

We will now have a closer look at the Ruby code. In a
.html.erb file, there are two kinds of Ruby code
instructions in addition to the HTML elements:

<%
… %>

Executes the Ruby code it contains, but does not output
anything (unless you explicitly use something like
print or puts).

<%=
… %>

Executes the Ruby code it contains and outputs the result as
text. Certain characters are automatically “escaped”.
If you do not want to output escaped text in a specific case, you
need to realise this with raw(string).

So provided an object has a method
.to_s or the object itself is already a
string, you can output it as result in the view, encapsulated
within <%= …
%>.

Let's use an example, to make sure it all makes sense.
We edit the app/views/example/test.html.erb as
follows:

Does it all make sense to you? Potentially, there are still two
open questions:

Q:

I don't understand anything. I can't cope with the Ruby
code. Could you please explain that again?

A:

Is it possible that you have not completely worked your
way through Chapter 2, Ruby Basics? Please do take
your time with it and have another thorough look. Otherwise,
the rest won't make any sense here.

Q:

I can understand the Ruby code and the HTML output. But
I don't get why some HTML code was rendered around it if I
didn't even write that HTML code. Where does it come from, and
can I influence it?

You are now going to learn the finer points of
erb step by step. Don't worry, it's neither magic nor
rocket science.

Layouts

The erb file in the directory
app/views/example/ only forms the core of the later
HTML page. By default, an automatically generated
app/views/layouts/application.html.erb is always
rendered around it. Let's have a closer look at it:

With <%= yield %> the View file is included
here. The three lines with the stylesheets, the JavaScript and
the csrf_meta_tags can stay as they are for now. They integrate default
CSS and JavaScript files. We'll have a look into that in Chapter 12, Asset Pipeline. No need to bother with that right
now.

The file
app/views/layouts/application.html.erb enables you
to determine the basic layout for the entire Rails application. If you
want to enter a <hr> for each page and above it a
text, then you can do this between the <%= yield %>
and the <body> tag:

You can also create other layouts in the directory
app/views/layouts/ and apply these layouts
depending on the relevant situation. But let's leave it for now. The
important thing is that you understand the basic concept.

Passing Instance Variables from a Controller to a View

One of the cardinal sins in the MVC model[20]is to put too much program logic into the view. That's more
or less what used to be done frequently in PHP programming in the past.
But one of the aims of MVC is that any HTML designer can create a view
without having to worry about the programming. Yeah, yeah, … if only it
was always that easy. But let's just play it through in our minds: if I
have a value in the controller that I want to display in the view, then
I need a mechanism for this. This is referred to as instance variable and always starts with a
@. If you are not 100 % sure any more which variable has
which scope, then
please have another quick look at the section called “Scope of Variables”.

In the following example, we insert an instance variable for the
current time in the controller and then insert it in the view. So we are
taking programming intelligence from the view to the controller.

In the view file
app/views/example/test.html.erb we can then access
this instance variable:

<p>
The current time is
<%= @current_time %>
</p>

With the controller and the view, we now have a clear separation
of programming logic and presentation logic. So now we can automatically
adjust the time in the controller in accordance with the user's time
zone, without the designer of the page having to worry about it. As
always, the method to_s is automatically
applied in the view.

I am well aware that no-one will now jump up from their chair and
shout: “Thank you for enlightening me! From now on, I will only
program neatly in accordance with MVC.” The above example is just
the first small step in the right direction and shows how we can easily
get values from the controller to the view with instance
variables.

Partials

Even with small web projects, there are often elements that appear
repeatedly, for example a footer on the
page with contact info or a menu. Rails gives us the option of
encapsulate this HTML code in form of “partials” and then integrating it
within a view. A partial is also stored in the directory
app/views/example/. But the file name must start
with an underscore (_).

Note

The term partial
indicates that these are parts of something, in other words, smaller
chunks of a template, a partial template.

As an example, we now add a mini footer to our page in a separate
partial. Copy the following content into the new file
app/views/example/_footer.html.erb:

Note

Yes, we should use an instance variable and put the programming
logic into the controller. But to keep it simpler I do it the dirty
way which is putting this little Date.today.year
programming in the view.

We edit the file
app/views/example/test.html.erb as follows and
insert the partial via the commandrender:

So now we have the following files in the directory
app/views/example:

$ ls app/views/example/
_footer.html.erb
test.html.erb
$

The new web page now looks like this:

Important

The name of a partial in the code is always specified
without the preceding underscore
(_) and without the file
extension .erb and .html. But
the actual file must have the underscore at the beginning of the
file name and end with the file extension .erb
and .html.

Partials can also be integrated from other areas of the
subdirectory app/views. For example, you can create
a directory app/views/shared for recurring and
shared content and create a file _footer.html.erb
in this directory. You would then integrate this file into the
erb code via the line:

<%= render "shared/footer" %>

Note

In a real-world project, you would - depending on your
programming preferences - not normally solve the footer problem by
using a partial that is called locally everywhere, but rather take
care of it centrally in the
app/views/layouts/application.html.erb.

Passing Variables to a
Partial

Partials are great in the sense of the DRY (Don't Repeat
Yourself) concept.
But what makes them really useful is the option of passing variables.
Let's stick with the copyright example. If we want to pass the start
year as value, we can integrate this by adding the following in the
file
app/views/example/_footer.html.erb:

Sometimes you need a partial that partially uses a local
variable and somewhere else you may need the same partial, but without
the local variable. We can take care of this in the partial itself
with an if statement: