About The Author

Jan Varwig is a programming language enthusiast, currently writing his CS diploma thesis about server-side JavaScript, and a software developer with 10 years of … More about Jan

Beginner's Guide To Ruby On Rails: Part 2

Quick Summary

Last week we published Getting Started With Ruby On Rails, the first part of our Ruby On Rails introduction. We explained basic ideas behind Ruby and presented concepts and essential components of the language. In this article you’ll learn more about Rails, you will learn how to get Ruby on Rails running on your computer, and get an overview of the basic functionality of Rails and demonstrate how Rails’ main parts work together. I assume you’re already familiar with some other form of Web development, whether PHP, Python, Perl or Java, and relational databases like MySQL. First, we’ll introduce Rails and Ruby and the basic ideas behind both. I’ll teach you just enough Ruby so that you understand the code samples. I’ll tell you how to get Ruby on Rails running on your computer, and I’ll give you an overview of the basic functionality of Rails and demonstrate how Rails’ main parts work together. After reading these parts, you should have an idea of whether Rails is for you. If you get the feeling that it is, I’ll point you to some good tutorials on the Web that you can use to learn Rails. I’ll also provide a lot of further reading recommendations so you can dig as deep into the topic as you like. You may want to take a look at the following related posts: * Getting Started With Ruby On Rails: Ruby * 10 Useful Tips For Ruby On Rails Developers

Table of Contents
Membership counter

Members support Smashing

Wonderful, friendly people who keep this lil' site alive — and get smarter every day.

Are you smashing, too? →

Last week we published Getting Started With Ruby On Rails, the first part of our Ruby On Rails introduction. We explained basic ideas behind Ruby and presented concepts and essential components of the language. In this article you’ll learn more about Rails, you will learn how to get Ruby on Rails running on your computer, and get an overview of the basic functionality of Rails and demonstrate how Rails’ main parts work together.

I assume you’re already familiar with some other form of Web development, whether PHP, Python, Perl or Java, and relational databases like MySQL. First, we’ll introduce Rails and Ruby and the basic ideas behind both. I’ll teach you just enough Ruby so that you understand the code samples. I’ll tell you how to get Ruby on Rails running on your computer, and I’ll give you an overview of the basic functionality of Rails and demonstrate how Rails’ main parts work together.

After reading these parts, you should have an idea of whether Rails is for you. If you get the feeling that it is, I’ll point you to some good tutorials on the Web that you can use to learn Rails. I’ll also provide a lot of further reading recommendations so you can dig as deep into the topic as you like.

You may want to take a look at the following related posts:

Get Rolling

To get your feet wet with Rails, it’s best to simply install it on your own machine and start playing around. This requires just a few steps.

On Windows do the following:

  1. Install Ruby 1.8.6 using the one-click installer from www.ruby-lang.org. Make sure to select “Enable Rubygems” during installation. It’s probably a good idea to install ruby as admin.
  2. Update Rubygems. Rubygems is Ruby’s package management system, and Rails needs a newer version than the one that ships with the installer. To do this, execute gem update --system in the console as admin. Next, you’ll need to add the GitHub gem server to Rubygems with gem sources -a http://gems.github.com
  3. Install Rails and its dependencies with gem install rails and gem install mysql. (You can use other databases, but MySQL is the easiest to set up.)
  4. Install the MySQL Database from mysql.com. If you’ve done Web development before, you probably already have it on your machine.
  5. Create a Rails application. Enter rails -d mysql <appname>. “Appname” will be the name of the sub-directory your app is created in.
  6. Go into the created application’s directory and execute ruby script/server. Point your browser to localhost:3000. You should see the Rails welcome page. Follow its instructions.

To edit Ruby code, you can use any text editor. If you just have to have a fancy IDE, try NetBeans. I recommend Notepad++, a great, lightweight freeware editor.

On a Mac, you’re lucky. Mac OS 10.5 comes with Ruby, Rails and SqLite3. You just need to update your packages by issuing a few commands:

sudo gem install rubygems-update
sudo update_rubygems

gem install rails
gem install mongrel

If you need more detailed help on installing Rails on 10.4 Tiger, check out the tutorial on the Rails wiki or in this blog post. Now you can create your app with rails <appname>.

On Linux, the installation depends on your distribution.

A Bird’s Eye View Of Rails’ Inner Workings

This is the part I find missing in most other tutorials about any topic. I want to present an overview of the most important components of Ruby on Rails to help you understand how they work together to process requests. I will be more detailed in the controller section because that’s the most important one, and if I left things out there I wouldn’t be able to paint the whole picture.

Controller

When the request hits your server running the Rails app, the first component handling it is the ActionController.

The ActionController and all of its parts correspond to the controller-part of the MVC stack. Before actually handling the request, the ActionController inspects it to determine which of the controllers in your application is responsible for the request.

These lookups are called routes and are defined in config/routes.rb. If you take a look in that file, you’ll see lines similar to these:

ActionController::Routing::Routes.draw do |map|
  map.resources :users
  map.connect ':controller/:action/:id'
end

The details of route definition could fill an article of their own. If you’re interested in its precise workings, take a look at the ActionController::Routing documentation in the Rails API.

Simplified, two kind of routes appear here. The last one is the traditional style of defining routes. These are formed like simple regular expressions, with the :foo part being a placeholder.

If a request’s URL matches one of these expressions, its parts are mapped to the placeholders. These are then examined to determine the correct controller, the action within the controller and further parameters like id (id always contains the id of the object that the client wants to work with). For example, a URL like /foo/bar/123 would be mapped to the FooController; the bar action and the value of params[:id] would be 123.

The first line is a shortcut to create a large number of those routes in one sweep. Routes created this way adhere to the REST principles. Again, this is a topic large enough to warrant its own article. For the sake of this introduction, let me just illustrate the effect of map.resources :users as an example. If you put such a line in your routes.rb you’re telling Rails that you want users to be a resource. That means seven routes are installed that all point to the UserController. These seven routes match not only against the URL of the request but also the HTTP method. The mappings are:

GET      /users            # will point to the index action
GET      /users/new        # will point to the new action
POST     /users            # will point to the create action
GET      /users/:id        # will point to the show action
GET      /users/:id/edit   # will point to the edit action
PUT      /users/:id        # will point to the update action
DELETE   /users/:id        # will point to the destroy action

All of these actions of the UserController are expected to behave in certain ways.

  • The index action should display a list of all existing users.
  • The new action should display a form for the creation of a new user that is submitted to /users via POST.
  • The create action should take the form’s input and create a new user in the database.
  • The show action should display the user with the corresponding id.
  • The edit action should display a form for editing the user. The form should submit to /users/:id/ via PUT.
  • The update action receives the form data and updates the user in the database.
  • The destroy action deletes the user from the database.

Because PUT and DELETE aren’t supported by all browsers, forms that are supposed to use these methods submit via POST and tell the server their intended method via a hidden form field named _method.

Once controller, action and parameters are determined, the action can be called. But before that actually happens, Rails inspects the filter chain for the action to see if there are any filters to be executed before the action runs. Such filters are incredibly useful for things like user authentication. To ensure that only logged-in users of your application can access certain actions, you would define a filter that checks the session for valid credentials. Such a filter could look like this:

class UserController < ApplicationController

  # Require valid login to access the update action
  before_filter(:require_login, :only => :update)

  # Lots of actions defined here
  # ...
  # ...

private

  def require_login
    render(:text => "Unauthorized", :status => 401) unless session[:user_valid]
  end

end

Let’s analyze this example line by line. The UserController inherits from the ApplicationController. All of your controllers should. The ApplicationController can then contain code that should be shared among all the controllers in your application. You could, for example, put the require_login filter in there to require a valid log-in for all your controllers.

The next line declares a before filter. By making the declaration using the symbol :require_login, you’re telling Rails to use the require_login method as a filter. This alone would apply the filter to all actions in the UserController. The additional parameter :only => :update tells Rails to use the filter only when the client wants to access the update action. In a real controller, this line would be followed by the definitions of all the actions your controller contains. In this example, they’re omitted for brevity.

The keyword private marks all the methods defined afterward as private to the UserController. This implies that they can’t be used as actions. We don’t want require_login to be used as an action, so we’re putting it here.

Require_login checks if the field :user_valid in the session is present. This is, of course, a pretty drastic simplification of a real authentication scheme, but it’s sufficient for the sake of illustrating filters. Unless a user is logged in, the filter renders a simple error message.

Now, here’s a detail you need to know to understand this. Rails works through all the filters applying to an action and only aborts request processing for three reasons:

  1. A filter raises an Error.
  2. A filter returns false.
  3. A filter renders somethings or redirects.

So, this single line is all that is needed to protect our sensitive actions against malicious clients. Again, I’m simplifying this a bit. To make an application really secure, you will of course need a little bit more code to properly maintain session state. To find out more about filters, read the ActionController::Filters::ClassMethods documentation in the Rails API.

Let’s see how Rails continues with the processing of the request.

After the client’s request has passed all filters, the action finally executes. Let’s run with our example from the filters section and assume the client wants to execute the update action after editing the user in a from provided by the edit action. Both actions could be defined like this:

def edit
  @user = User.find(params[:id])
end

def update
  @user = User.find(params[:id])
  if @user.update_attributes(params[:user])
    redirect_to users_url
  else
    render :action => :edit
  end
end

Let’s work through this line by line again. First, note that actions are defined as simple parameter-less methods on the controller. Their input and output is realized a little differently from what you’d expect from a method. Actions retrieve all the information they need to process the request from their controller through a few accessors, mainly params and session. There are more (cookies, request), but they’re not used nearly as often as these two, and I don’t want to complicate matters more than is necessary here.

The params method returns all the parameters of a request. These usually result from its querystrings or the postbody, but can also be created from JSON or XML data structures. Through routes, parts of the URL can also become parameters. This is where the :id parameter in the example is read from. If the client requests /users/123/edit/ and we have a route definition map.resources :users, then 123 becomes the :id parameter for the edit action, because the route definition generates (among others) a route that looks like this:

map.route '/users/:id/edit',
          :controller => 'users',
          :action     => 'edit',
          :method     => :get

<!-- The "session" method can be used to access data in the session. Whatever you put in here will be available in subsequent actions in the same session. This is commonly used to store log-in information or things like shopping cart contents. -->

For output, an action basically has two options. It can either redirect the user or render a template. The templates for a Rails application are organized the same way the controllers are. They reside in app/templates/<controllername>/<action>.html.erb, and if no output is specified in the action, Rails renders the template belonging to that action by default. That’s why you don’t see any output code in the edit action. The only line in edit pulls the user we want to edit out of the database and puts it into an instance variable of the controller to make it available to the template.

The update action begins with the same statement, again fetching the user form the database. In its next step, the user’s attributes are updated with the data that the action received from the client-side form. The update returns true on success. In this case, the client is redirected to the list of users.

This redirection deserves closer inspection. The redirect_to command takes a URL, but instead of hard-coding these URLs (/users in this case), it is conventional to use URL helpers like users_url. The helpers are generated automatically by the route or resource definitions.

If updating the user’s attributes does not succeed, two things happen inside the update_attributes call. First the user’s errors property will be filled with details on why the update didn’t succeed, and the call will return false instead of true. As a result, the client is not redirected; instead, render is called, with :action => :edit as its parameter. This tells render to render the template belonging to the edit action of the current controller.

Why not redirect to the edit action, you may ask? We could do that, but we’d lose all the edits we made to the user and lose information on the errors that occurred. When the edit-template is rendered instead during the processing of the update action, the user that failed to update is still in memory with all its pending edits and the errors. We can use this data in the template to pre-fill the form with the values we just entered (but didn’t save to the database) and provide information to the client on what went wrong.

There’s one last important thing to note here about render and redirect_to. It is not apparent from these examples, but calling render or redirect_to does not stop the processing of the action. These are both just methods and not special control flow statements. So, when render is called, the template isn’t rendered yet; rather, the controller renders the template after the action has processed. Any statements following a render are still executed.

Model

The second important part of MVC in Rails is the Model. Its role is played by the ActiveRecord module, an implementation of the pattern of the same name. ActiveRecord::Base functions as a base class for the models in your application. If you derive your models from this class, you’ll have them automatically linked to tables in your database and can very easily load, edit, save, create, delete or list them. Mappings between the structure and behavior of your models and the tables in the database are fully automated mostly, provided that you adhere to a few rules in the design of your tables. The general principles are:

  1. Your table name is the pluralized, underscored variant of your classname. So, a class User would be mapped to the table users.CookieRecipe would be mapped to cookie_recipes.
  2. Your table needs to have its primary key on an integer column called id with the auto increment property.
  3. Associations to other tables are stored in columns that are named after them. If you want to store posts belonging to a user, the posts table would need a user_id column

If you have a table and class that are connected via their name, like users and User, any column in the table is available on the model as a property. If you want to create a User, you’d just instantiate an object in Rails:

u = User.new

Then you can begin setting its properties:

u.name = "Michael"
u.age  = 35

You could also provide these settings upon creation:

u = User.new(:name => "Michael", :age => 35)

To store the new user in the database, tell it to save:

u.save

You can find records in a lot of ways:

u = User.find(123)               # finds the user with id 123
u = User.find(:all)              # returns an array containing all users
u = User.find_by_name("Michael") # a "magic" finder

I don’t want to go into the details of all of these options. You can find them all in the ActiveRecord::Base module documentation in the Rails API. I’d rather introduce two important features of ActiveRecord: associations and validations.

I have already mentioned associations briefly and given an example of posts belonging to users. How would you actually implement that? Well, as mentioned, you first put a user_id column in the posts table to link the two tables. Then you need to make your models aware of the link (unfortunately, it doesn’t do that automatically). But don’t worry, you only need two lines of code for that:

class User < ActiveRecord::Base
  has_many :posts
end

class Post < ActiveRecord::Base
  belongs_to :user
end

That’s it. These two lines make helpers available in both models that allow for navigating the models. Given a post, you could access its user via post.user or get all posts of a user by saying user.posts.

Validations are constraints that you can define in your model to ensure that the model is only saved to the database if those constraints are met. Rails provides a lot of predefined validations that ensure that a property isn’t empty, is within a certain numeric range or matches a regular expression. But you can basically use anything you can write down in code as a validation. Say you want to ensure that your posts have titles not longer than 100 characters and that the post body is always present. You would extend your Post class like this:

class Post < ActiveRecord::Base
  belongs_to :user

  validates_presence_of :body
  validates_length_of   :title, :maximum => 100
end

A call to the save method on a post that doesn’t comply with these restrictions will return false, and the post will not be saved to the database. You can then examine the post’s errors object by accessing post.errors and communicate to the users what went wrong. The Rails-provided validations all come with descriptive error messages that you could retrieve with post.errors.full_messages, for example.

ActiveRecord has a lot more depth and functionality than presented here. Even complex models and their relations can be handled pretty comfortably. But presenting all this exceeds the scope of this article. The API doesn’t help much if you want to explore all these possibilities; so, to get a deeper introduction, I recommend the Rails Envy ActiveRecord tutorial.

View

We’re almost at the end of our overview. The last missing part is MVC’s V, the View. All the components related to this are aggregated under the ActionView module. At the core of Rails’ views are the ERB templates, but they are backed by a large library of helpers that can be used to generate forms, URLs, sub-templates and other little tools that can make your life easier.

In the controller example, I talked about how the render method is used to render a template. An action that doesn’t explicitly render or redirect automatically renders its corresponding template in app/templates/<controller>/<action>.html.erb. The file extension .erb stands for “Embedded Ruby,” and that’s what the templates are: HTML files that are dynamically filled with content through the use of special script tags that contain Ruby code. These special tags work very similar to the ones PHP uses. Let’s take a look at an example:

<html>
  <head>
    <title><%= @pagetitle %></title>
  </head>
  <body>
    <h1>Post: <%= h @post.title %></h1>
    <p>Written on <%= @post.date %></p>

    <div id="postcontent">
      <%= h @post.content %>
    </div>

    <% if @post.user.posts.count > 1 %>
      <p>Other posts by <%= @post.user.name %>:</p>
      <ul>
        <% @post.user.posts.each do |post| %>
          <li><%= h post.title %></li>
        <% end %>
      </ul>
    <% end %>
  </body>
</html>

Tags beginning with <%= evaluate the expression they contain and insert them into the document. The little h you see sometimes is a helper function provided by ActionView that escapes characters that are not valid HTML. You should always use this if you’re displaying user-entered content to prevent cross-site scripting attacks.

Below the postcontent div, you can see another type of erb tag, without the equals sign. This means that its content is executed but not inserted into the document. We’re opening a conditional statement here. Everything between the if and the end will only be executed if the current post’s user has other posts. This affects both Ruby and HTML code.

The next tag is also pretty interesting and different from the ones used before. We’re combining the power of Ruby blocks here with ERB to iterate over a user’s posts. The each method executes its block for each of the members of a collection and makes the current member available to the block. I’ve called the block’s parameter post here, so we can refer to the current post under this name within the block. In ERB, you can put HTML within blocks just as if it were code.

You’ll notice that I’m using two instance variables in this template, @pagetitle and @post. They are the main means of passing data from the controller to the template. Instance variables that exist in the controller can also be accessed in the template. It’s that simple.

From the content of the page, you can see that we’re probably rendering the show action of a post’s resource here. The controller action to feed this template with data could look like this:

def show
  @post = Post.find(params[:id)
end

The @pagetitle could be the result of a before filter:

before_filter :set_title
def set_title
  @pagetitle = "Showing Post #{params[:id]}"
end

Rails’ templates can harness the full power of the Ruby language and have access to the full stack right down to the models. This power can easily be misused to put controller logic or model operations into the templates. But you’re only hurting yourself (and your colleagues) if you do that. You should only put code in the templates that is directly related to displaying data.

As with ActiveRecord, this only scratches the surface of what’s possible with ActionView. Three of the most useful features not introduced here are:

  • Layouts that can be nested so that you don’t have to repeat identical structures in your templates over and over.
  • Partials, small template snippets that can be used to render collections and inserted into other templates
  • Generation of JSON and XML to create Web services, AJAX interfaces and RSS feeds.

To go deeper into the topic, check out the Layouts and Rendering in Rails guide on Rails Guides.

Learning From Rails

Rails takes Ruby’s aim of increasing programmer productivity and happiness and applies it to Web frameworks. Its debut was a truly revelatory experience because it showed developers that that power doesn’t have to come with the clumsiness that other frameworks exhibited at the time.

Today, the ideas of Rails can be found in many imitators in other languages, but if you’re not tied to any one of them, Ruby on Rails is definitely worth checking out. You’ll rediscover the fun in programming, and even if you don’t stick with Rails, you definitely won’t regret the learning experience.

The greatest thing about Rails, however, is how it can change your perception of programming in general once you understand its design and the reasons behind it.

First, simply using Ruby – a language that’s quite different from ones you’ve used before, yet similar enough not to be totally alienating – opens up your mind to new ways of thinking and new ways of perceiving programming languages. You’ll suddenly begin to question things you’ve taken for granted. You’ll frown at first on the prospect of opening up and redefining core classes at runtime, but once you’ve done it and seen that your program still runs and looks nicer than before, you’ll appreciate the flexibility and also become a more responsible programmer. You’ll curse every semicolon and every empty pair of braces that other languages force upon you.

For many programmers, Ruby even paved the way to radically different territory, namely functional programming. Ruby is an imperative language, but its treatment of code blocks as objects equal to Strings, Numbers or any other class and its support of closures will slowly prepare your mind for languages like Lisp, Haskell and OCaml, where passing around functions is the predominant way of writing programs. You’ll have a much broader palette of solutions for the problems you’re tackling each day, and those problems will stop looking like all nails.

Rails very much builds upon these wisdoms and makes much use of meta-programming (class rewriting) and functional programming principles. In this way, Rails becomes more than a framework, and becomes rather a domain-specific language for writing Web applications. The exploitation of Ruby’s dynamic features enables a brevity in Rails’ API that does not obscure your code’s intention. After using Rails for a while, you’ll start to develop your own programs in this way.

Rails encourages strict separation of code between your models, controllers and views. Once you’ve written an app in this straightjacket, you’ll begin to see its tremendous benefits. You will develop a sharper eye for the correct location of code. Things you’ve put in your controllers in the past will take their place in the models, and your design will become more fluent, cleaner and more flexible, especially if you let Rails encourage you to thoroughly test your app.

Even if your flirtation with Rails doesn’t turn into a long-term relationship, you’ll gain invaluable experiences that will improve your style in whatever you develop in future.

Further resources

In the hope that your interest has now been piqued and you have an idea of what to expect, I’d like to point you to some resources that will really teach you how to write Web application in Rails.

Further, I’ll point you to some important sources of news, because despite its maturity, Rails is moving at blazing speeds. Don’t misunderstand me: you won’t have to study new features each week to keep up with programming in Rails, but by monitoring the right news sources, you’ll learn invaluable tips and tricks that you won’t find in the tutorials.

First of all, there are books. The advantage of computer books is that they’re usually comprehensive and professionally edited. The disadvantage is that most of them are outdated by the day they hit the shelves. So, the only books you should really bother reading are the ones that are just out. Fortunately, the standard Rails manual, “Agile Web Development with Rails” is just receiving the finishing touches for its third edition, which will cover the most recent changes in the framework. It’s good for beginners and doesn’t go very deep, but that’s okay. If you want to go deep, you can just read blog articles about the subjects you’re interested in after you’re done with the book.

To learn Ruby, you could try Programming Ruby (the “Pickaxe”), the guide written by the Pragmatic Programmers that first brought Ruby to the west. Its first edition is even free and can be found at ruby-doc.org alongside the official Ruby API. The second (and upcoming third) edition is definitely worth the money, though, especially for its chapter about the inner details of Ruby’s object and method dispatch system.

People who don’t like the Pickaxe usually recommend Hal Fulton’s “The Ruby Way,” which teaches the language in a more task-oriented way.

u.save

You can find records in a lot of ways:

u = User.find(123)               # finds the user with id 123
u = User.find(:all)              # returns an array containing all users
u = User.find_by_name("Michael") # a "magic" finder

I don’t want to go into the details of all of these options. You can find them all in the ActiveRecord::Base module documentation in the Rails API. I’d rather introduce two important features of ActiveRecord: associations and validations.

I have already mentioned associations briefly and given an example of posts belonging to users. How would you actually implement that? Well, as mentioned, you first put a user_id column in the posts table to link the two tables. Then you need to make your models aware of the link (unfortunately, it doesn’t do that automatically). But don’t worry, you only need two lines of code for that:

class User < ActiveRecord::Base
  has_many :posts
end

class Post < ActiveRecord::Base
  belongs_to :user
end

That’s it. These two lines make helpers available in both models that allow for navigating the models. Given a post, you could access its user via post.user or get all posts of a user by saying user.posts.

Validations are constraints that you can define in your model to ensure that the model is only saved to the database if those constraints are met. Rails provides a lot of predefined validations that ensure that a property isn’t empty, is within a certain numeric range or matches a regular expression. But you can basically use anything you can write down in code as a validation. Say you want to ensure that your posts have titles not longer than 100 characters and that the post body is always present. You would extend your Post class like this:

class Post < ActiveRecord::Base
  belongs_to :user

  validates_presence_of :body
  validates_length_of   :title, :maximum => 100
end

A call to the save method on a post that doesn’t comply with these restrictions will return false, and the post will not be saved to the database. You can then examine the post’s errors object by accessing post.errors and communicate to the users what went wrong. The Rails-provided validations all come with descriptive error messages that you could retrieve with post.errors.full_messages, for example.

ActiveRecord has a lot more depth and functionality than presented here. Even complex models and their relations can be handled pretty comfortably. But presenting all this exceeds the scope of this article. The API doesn’t help much if you want to explore all these possibilities; so, to get a deeper introduction, I recommend the Rails Envy ActiveRecord tutorial.

View

We’re almost at the end of our overview. The last missing part is MVC’s V, the View. All the components related to this are aggregated under the ActionView module. At the core of Rails’ views are the ERB templates, but they are backed by a large library of helpers that can be used to generate forms, URLs, sub-templates and other little tools that can make your life easier.

In the controller example, I talked about how the render method is used to render a template. An action that doesn’t explicitly render or redirect automatically renders its corresponding template in app/templates/<controller>/<action>.html.erb. The file extension .erb stands for “Embedded Ruby,” and that’s what the templates are: HTML files that are dynamically filled with content through the use of special script tags that contain Ruby code. These special tags work very similar to the ones PHP uses. Let’s take a look at an example:

<html>
  <head>
    <title><%= @pagetitle %></title>
  </head>
  <body>
    <h1>Post: <%= h @post.title %></h1>
    <p>Written on <%= @post.date %></p>

    <div id="postcontent">
      <%= h @post.content %>
    </div>

    <% if @post.user.posts.count > 1 %>
      <p>Other posts by <%= @post.user.name %>:</p>
      <ul>
        <% @post.user.posts.each do |post| %>
          <li><%= h post.title %></li>
        <% end %>
      </ul>
    <% end %>
  </body>
</html>

Tags beginning with <%= evaluate the expression they contain and insert them into the document. The little h you see sometimes is a helper function provided by ActionView that escapes characters that are not valid HTML. You should always use this if you’re displaying user-entered content to prevent cross-site scripting attacks.

Below the postcontent div, you can see another type of erb tag, without the equals sign. This means that its content is executed but not inserted into the document. We’re opening a conditional statement here. Everything between the if and the end will only be executed if the current post’s user has other posts. This affects both Ruby and HTML code.

The next tag is also pretty interesting and different from the ones used before. We’re combining the power of Ruby blocks here with ERB to iterate over a user’s posts. The each method executes its block for each of the members of a collection and makes the current member available to the block. I’ve called the block’s parameter post here, so we can refer to the current post under this name within the block. In ERB, you can put HTML within blocks just as if it were code.

You’ll notice that I’m using two instance variables in this template, @pagetitle and @post. They are the main means of passing data from the controller to the template. Instance variables that exist in the controller can also be accessed in the template. It’s that simple.

From the content of the page, you can see that we’re probably rendering the show action of a post’s resource here. The controller action to feed this template with data could look like this:

def show
  @post = Post.find(params[:id)
end

The @pagetitle could be the result of a before filter:

before_filter :set_title
def set_title
  @pagetitle = "Showing Post #{params[:id]}"
end

Rails’ templates can harness the full power of the Ruby language and have access to the full stack right down to the models. This power can easily be misused to put controller logic or model operations into the templates. But you’re only hurting yourself (and your colleagues) if you do that. You should only put code in the templates that is directly related to displaying data.

As with ActiveRecord, this only scratches the surface of what’s possible with ActionView. Three of the most useful features not introduced here are:

  • Layouts that can be nested so that you don’t have to repeat identical structures in your templates over and over.
  • Partials, small template snippets that can be used to render collections and inserted into other templates
  • Generation of JSON and XML to create Web services, AJAX interfaces and RSS feeds.

To go deeper into the topic, check out the Layouts and Rendering in Rails guide on Rails Guides.

Learning From Rails

Rails takes Ruby’s aim of increasing programmer productivity and happiness and applies it to Web frameworks. Its debut was a truly revelatory experience because it showed developers that that power doesn’t have to come with the clumsiness that other frameworks exhibited at the time.

Today, the ideas of Rails can be found in many imitators in other languages, but if you’re not tied to any one of them, Ruby on Rails is definitely worth checking out. You’ll rediscover the fun in programming, and even if you don’t stick with Rails, you definitely won’t regret the learning experience.

The greatest thing about Rails, however, is how it can change your perception of programming in general once you understand its design and the reasons behind it.

First, simply using Ruby – a language that’s quite different from ones you’ve used before, yet similar enough not to be totally alienating – opens up your mind to new ways of thinking and new ways of perceiving programming languages. You’ll suddenly begin to question things you’ve taken for granted. You’ll frown at first on the prospect of opening up and redefining core classes at runtime, but once you’ve done it and seen that your program still runs and looks nicer than before, you’ll appreciate the flexibility and also become a more responsible programmer. You’ll curse every semicolon and every empty pair of braces that other languages force upon you.

For many programmers, Ruby even paved the way to radically different territory, namely functional programming. Ruby is an imperative language, but its treatment of code blocks as objects equal to Strings, Numbers or any other class and its support of closures will slowly prepare your mind for languages like Lisp, Haskell and OCaml, where passing around functions is the predominant way of writing programs. You’ll have a much broader palette of solutions for the problems you’re tackling each day, and those problems will stop looking like all nails.

Rails very much builds upon these wisdoms and makes much use of meta-programming (class rewriting) and functional programming principles. In this way, Rails becomes more than a framework, and becomes rather a domain-specific language for writing Web applications. The exploitation of Ruby’s dynamic features enables a brevity in Rails’ API that does not obscure your code’s intention. After using Rails for a while, you’ll start to develop your own programs in this way.

Rails encourages strict separation of code between your models, controllers and views. Once you’ve written an app in this straightjacket, you’ll begin to see its tremendous benefits. You will develop a sharper eye for the correct location of code. Things you’ve put in your controllers in the past will take their place in the models, and your design will become more fluent, cleaner and more flexible, especially if you let Rails encourage you to thoroughly test your app.

Even if your flirtation with Rails doesn’t turn into a long-term relationship, you’ll gain invaluable experiences that will improve your style in whatever you develop in future.

Further resources

In the hope that your interest has now been piqued and you have an idea of what to expect, I’d like to point you to some resources that will really teach you how to write Web application in Rails.

Further, I’ll point you to some important sources of news, because despite its maturity, Rails is moving at blazing speeds. Don’t misunderstand me: you won’t have to study new features each week to keep up with programming in Rails, but by monitoring the right news sources, you’ll learn invaluable tips and tricks that you won’t find in the tutorials.

First of all, there are books. The advantage of computer books is that they’re usually comprehensive and professionally edited. The disadvantage is that most of them are outdated by the day they hit the shelves. So, the only books you should really bother reading are the ones that are just out. Fortunately, the standard Rails manual, “Agile Web Development with Rails” is just receiving the finishing touches for its third edition, which will cover the most recent changes in the framework. It’s good for beginners and doesn’t go very deep, but that’s okay. If you want to go deep, you can just read blog articles about the subjects you’re interested in after you’re done with the book.

To learn Ruby, you could try Programming Ruby (the “Pickaxe”), the guide written by the Pragmatic Programmers that first brought Ruby to the west. Its first edition is even free and can be found at ruby-doc.org alongside the official Ruby API. The second (and upcoming third) edition is definitely worth the money, though, especially for its chapter about the inner details of Ruby’s object and method dispatch system.

People who don’t like the Pickaxe usually recommend Hal Fulton’s “The Ruby Way,” which teaches the language in a more task-oriented way.

If you’re just entering the world of Rails, you’ll also have access to what will probably be a pretty awesome library of documentation (if it isn’t already!). A few months ago, the Rails team launched an effort to provide comprehensive, up-to-date and free information about everything Rails at Rails Guides.

If you’ve taken your first steps, you should subscribe to the official Ruby on Rails blog, mainly for important announcements and its “This Week in Rails” feature, which provides a very convenient overview of the development of Rails.

If you want to keep in touch with the greater Rails eco-system, you should subscribe to the Rails Envy podcast. These guys will point you to nice plug-ins, tips, tricks and important blog posts every week.

You could, of course, just read those blogs yourself, but beware: Rails has a lot going on in it, and I prefer to have the information predigested in some form. However, if you’d like something to chew on during those boring hours at work, check out these blogs:

Should you get stuck in your adventures, Googling often helps because most of the problems that beginners experience are similar, and for almost any hurdle you may encounter, somebody somewhere has already written a blog post about it. If this is not the case with your problem, ask for help on the Ruby on Rails mailing list or the Ruby mailing list. The people in the Ruby community are usually very friendly and helpful.

You may want to take a look at the following related posts:

Smashing Editorial (al)