A view is what is responsible for generating the actual HTML content in a Ruby on Rails web application. The controller accepts the request and retrieves data from the model, the model handles all the data, and the view outputs the HTML. However, there are a few things you need to know before digging in.
There can be more than one layout in a project. For example, maybe the admin gets a different layout with an extra sidebar or something, or just different layouts on different types of pages (blog gets a skinny layout, but forums get a wider layout). However, we'll just look at the application layout for now.
When you first generate a project, this is what the app/views/layouts/application.html.erb file looks like.
Nothing special here, but wait a minute, those aren't HTML tags! What are these <%= … %> type tags? It's called ERB, or "embedded Ruby."
ERB - Embedded Ruby
Views that output only HTML would be quite boring. Some systems implement a kind of templating engine, where you give a template a set of variables and special meta-tags inside this template substitute for the variables given. This is an OK setup, but you hit limitations in it quite fast. What if you want to produce one type of output if the string is really long, and another if it's short? If the templating engine provides no conditionals, you just can't. You'll have to hack that in another way, possibly polluting your controller with HTML. And on top of all that, you have to learn yet another language. All you want to do is output some HTML and you have to use 3 or 4 languages at a time? There's got to be a better way.
This is what ERB is all about. These funky tags with the percent signs allow you to insert Ruby code right into your HTML code. If the tag has an equals sign, like <%= … %>, then the string value of whatever that Ruby code evaluates to is inserted into the HTML output. You'll often see single variables in these tags, outputting the string representation (it'll call to_s on the object if it's not already a string) of that object into the stream, like with <%= @first_name %>.
There are a few other ERB tags you should know about.
- <%= code %> - Run the code and output the resulting object to the output stream.
- < code %> - Note the lack of an equals sign. This will not output the resulting object. This is most seen with conditionals and loops.
- <# comment %> - A Ruby comment that will not appear in the output at all.
There are a few other things that ERB recognizes that don't have the same tag structure, but since they save so few characters and don't follow the pattern, they're not often used.
Tags and HTML code can be freely intermixed. For example, this short snippet outputs all elements of a list as an HTML unordered list.
<ul> <% @names.each do|name| %> <li><%= name.last %>, <%= name.first %></li> <% end %> </ul>
If you've worked with PHP before, you'll be quite familiar with this. Note that the block passed to the each method is spread over several ERB tabs. This doesn't break either the structure of the HTML or the Ruby code, it's all rather elegant.
The actual views themselves will be stored in app/views/_controller_/_action_.html.erb. Each action has its own view. These files are very much like the template view we saw above, but only the HTML for the content itself is in the view. In fact, the template actually interacts with the action's view, the <%= yield %> line is where the action's view is called and its output added to the template.
When an action's view is called, all of the instance variables in the controller instance are available in the view. This is, more or less, the only way to get data into the view, store it in an instance variable before you call the view. They'll show up as instance variables in the view itself, though the view is being run in a totally different class, that's implemented with a bit of Ruby-fu, but it makes everything so consistent and tidy.
There's not all that much that can be said about views, actually. They're one of the simpler pieces of Rails, and you generally don't see much Ruby code in them other than loops and conditionals. In fact, if you find yourself putting more code in a view, you should stop and think whether that really belongs there, or you're just putting it there because you don't know a better place for it. Just remember, code more complex than simple conditionals or loops does not belong in views.