Beginner’s Guide To Ruby On Rails: Part 2
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:
- 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.
- 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 withgem sources -a https://gems.github.com
- Install Rails and its dependencies with
gem install rails
andgem install mysql
. (You can use other databases, but MySQL is the easiest to set up.) - Install the MySQL Database from mysql.com. If you’ve done Web development before, you probably already have it on your machine.
- Create a Rails application. Enter
rails -d mysql <appname>
. “Appname” will be the name of the sub-directory your app is created in. - Go into the created application’s directory and execute
ruby script/server
. Point your browser tolocalhost: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
viaPOST
. - 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/
viaPUT
. - 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:
- A filter raises an Error.
- A filter returns false.
- 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:
- Your table name is the pluralized, underscored variant of your classname. So, a class
User
would be mapped to the tableusers
.CookieRecipe
would be mapped tocookie_recipes
. - Your table needs to have its primary key on an integer column called
id
with theauto increment
property. - 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 auser_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:
- Ryan’s Scraps
- has_many :through
- Robby on Rails
- Jamis Buck’s blog
- caboose
- Ilya Grigorik’s blog
- On Rails
- nano RAILS
- Railscasts
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.
Related posts
You may want to take a look at the following related posts: