Chapter 1. Zero to Sixty: Introducing Rails

Rails may just be the most important open source project to be introduced in the past 10 years. It’s promoted as one of the most productive web development frameworks of all time and is based on the increasingly important Ruby programming language. What has happened so far?

  • By December 2006, you’re likely to see more published books on Rails than any of Java’s single flagship frameworks, including JSF, Spring, or Hibernate.

  • The Rails framework has been downloaded at least 500,000 times in only its second year, as of May 2006. These statistics compare favorably with the most popular open source frameworks in any language.[*]

  • The Rails community mailing lists get hundreds of notes a day, compared to dozens on the most popular web development frameworks in other languages.

  • The Rails framework has caused an explosion in the use of the Ruby programming language, which has been relatively obscure until recently.

  • The Rails buzz generates increasingly hot debates on portals that focus on other programming languages. The Java community in particular has fiercely debated the Rails platform.

You don’t have to go far to find great overviews of Rails. You can watch several educational videos that show Rails in action, narrated by the founder David Heinemeier Hansson. You can watch him build simple working applications, complete with a backing database and validation, in less than 10 minutes. But unlike the many quick-and-dirty environments you’ve seen, Rails lets you keep the quick and leave the dirty behind. It lets you build clean applications based on the model-view-controller philosophy. Rails is a special framework.

Sure, Rails has its limitations. Ruby has poor support for object-relational mapping (ORM) for legacy schemas; the Rails approach is less powerful than Java’s approach, for example.[*] Ruby does not yet have flagship integrated development environments. Every framework has limitations, and Rails is no different. But for a wide range of applications, the strengths of Rails far outpace its weaknesses.

Rails Strengths

As you go through this book, you’ll learn how Rails can thrive without all of the extensive libraries required by other languages. Ruby’s flexibility lets you extend your applications in ways that might have been previously unavailable to you. You’ll be able to use a Rails feature called scaffolding to put database-backed user interfaces in front of your customers quickly. Then, as you improve your code, the scaffolding melts away. You’ll be able to build database-backed model objects with just a couple of lines of code, and Rails will fill in the tedious details.

The most common programming problem in today’s typical development project involves building a web-based user interface to manage a relational database. For that class of problems, Rails is much more productive than any other web development framework either of us has ever used. The strengths aren’t limited to any single groundbreaking invention; rather, Rails is packed with features that make you more productive, with many of the following features building on one other:

Metaprogramming

Metaprogramming techniques use programs to write programs. Other frameworks use extensive code generation, which gives users a one-time productivity boost but little else, and customization scripts let the user add customization code in only a small number of carefully selected points. Metaprogramming replaces these two primitive techniques and eliminates their disadvantages. Ruby is one of the best languages for metaprogramming, and Rails uses this capability well.[]

Active Record

Rails introduces the Active Record framework, which saves objects to the database. Based on a design pattern cataloged by Martin Fowler, the Rails version of Active Record discovers the columns in a database schema and automatically attaches them to your domain objects using metaprogramming. This approach to wrapping database tables is simple, elegant, and powerful.

Convention over configuration

Most web development frameworks for .NET or Java force you to write pages of configuration code. If you follow suggested naming conventions, Rails doesn’t need much configuration. In fact, you can often cut your total configuration code by a factor of five or more over similar Java frameworks just by following common conventions.

Scaffolding

You often create temporary code in the early stages of development to help get an application up quickly and see how major components work together. Rails automatically creates much of the scaffolding you’ll need.

Built-in testing

Rails creates simple automated tests you can then extend. Rails also provides supporting code called harnesses and fixtures that make test cases easier to write and run. Ruby can then execute all your automated tests with the rake utility.

Three environments: development, testing, and production

Rails gives you three default environments: development, testing, and production. Each behaves slightly differently, making your entire software development cycle easier. For example, Rails creates a fresh copy of the Test database for each test run.

There’s much more, too, including Ajax for rich user interfaces, partial views and helpers for reusing view code, built-in caching, a mailing framework, and web services. We can’t get to all of Rails’ features in this book; however, we will let you know where to get more information. But the best way to appreciate Rails is to see it in action, so let’s get to it.

Putting Rails into Action

You could manually install all of the components for Rails, but Ruby has something called gems. The gem installer accesses a web site, Ruby Forge, and downloads an application unit, called a gem, and all its dependencies. You can install Rails through gems, requesting all dependencies, with this command:[*]

gem install rails --include-dependencies

That’s it—Rails is installed. There’s one caveat: you also need to install the database support for your given database. If you’ve already installed MySQL, you’re done. If not, go to http://rubyonrails.org for more details on Rails installation. Next, here’s how to create a Rails project:

>rails chapter-1
      create
      create  app/controllers
      create  app/helpers
      create  app/models
      create  app/views/layouts
      create  config/environments
      create  components
      create  db
      create  doc
      create  lib

...
      create  test/mocks/development
      create  test/mocks/test
      create  test/unit
      create  vendor
...
      create  app/controllers/application.rb
      create  app/helpers/application_helper.rb
      create  test/test_helper.rb
      create  config/database.yml
...

We truncated the list, but you get the picture.

Organization

The directories created during installation provide a place for your code, scripts to help you manage and build your application, and many other goodies. Later, we’ll examine the most interesting directories in greater detail. For now, let’s take a quick pass through the directory tree in the project we created:

app

This application organizes your application components. It’s got subdirectories that hold the view (views and helpers), controller (controllers), and the backend business logic (models).

components

This directory holds components—tiny self-contained applications that bundle model, view, and controller.

config

This directory contains the small amount of configuration code that your application will need, including your database configuration (in database.yml), your Rails environment structure (environment.rb), and routing of incoming web requests (routes.rb). You can also tailor the behavior of the three Rails environments for test, development, and deployment with files found in the environments directory.

db

Usually, your Rails application will have model objects that access relational database tables. You can manage the relational database with scripts you create and place in this directory.

doc

Ruby has a framework, called RubyDoc, that can automatically generate documentation for code you create. You can assist RubyDoc with comments in your code. This directory holds all the RubyDoc-generated Rails and application documentation.

lib

You’ll put libraries here, unless they explicitly belong elsewhere (such as vendor libraries).

log

Error logs go here. Rails creates scripts that help you manage various error logs. You’ll find separate logs for the server (server.log) and each Rails environment (development.log, test.log, and production.log).

public

Like the public directory for a web server, this directory has web files that don’t change, such as JavaScript files (public/javascripts), graphics (public/images), stylesheets (public/stylesheets), and HTML files (public).

script

This directory holds scripts to launch and manage the various tools that you’ll use with Rails. For example, there are scripts to generate code (generate) and launch the web server (server). You’ll learn much more about using these scripts throughout this book.

test

The tests you write and those Rails creates for you all go here. You’ll see a subdirectory for mocks (mocks), unit tests (unit), fixtures (fixtures), and functional tests (functional). We comprehensively cover testing in Chapter 7.

tmp

Rails uses this directory to hold temporary files for intermediate processing.

vendor

Libraries provided by third-party vendors (such as security libraries or database utilities beyond the basic Rails distribution) go here.

Except for minor changes between releases, every Rails project will have the same structure, with the same naming conventions. This consistency gives you a tremendous advantage; you can quickly move between Rails projects without relearning the project’s organization. The Rails framework itself also relies on this consistency because the different Rails frameworks will often discover files solely on naming conventions and directory structure. For example, later in this example, you’ll see the controller invoke views without any custom code.

The Web Server

Now that we’ve got a project, let’s start a server. Type cd chapter-1 to change to your project directory. Use the script/server script to start an instance of the WEBrick server, configured for development. If you’re running Windows, preface each call to a script with ruby, and you can use either forward or backward slashes. If you’re using a Unix derivative, you can omit the ruby keyword:

> ruby script/server
=> Booting WEBrick...
=> Rails application started on http://0.0.0.0:3000
=> Ctrl-C to shutdown server; call with --help for options
[2006-05-11 07:32:08] INFO  WEBrick 1.3.1
[2006-05-11 07:32:08] INFO  ruby 1.8.4 (2005-12-24) [i386-mswin32]
[2006-05-11 07:32:08] INFO  WEBrick::HTTPServer#start: pid=94884 port=3000

Notice a couple of details:

  • The server started on port 3000. You can change the port by editing the script/server script. See the sidebar "Configuring the Server" for more configuration options.

  • We started an instance of WEBrick, a pure Ruby server.

  • Ruby will also let you use a backward slash as a path delimiter on the command line, but on Unix you must use the forward slash. Some prefer the backslash because it allows you to use the tab completion feature in the MS-DOS command prompt.

Point your browser to http://127.0.0.1:3000/ or http://localhost:3000/. You’ll see the Rails welcome screen pictured in Figure 1-1. Don’t worry about the details of the request yet; for now, know that Rails is running and working correctly.

The Rails welcome screen
Figure 1-1. The Rails welcome screen

So far, you’ve only typed a few words, and you’ve already set up the build environment and the web server, and verified that the server is running. In the development environment, you’ll normally leave the server up, rebooting only to change the database configuration.

Choosing a Server

Rails will run on many different web servers. Most of your development will be done using WEBrick, but you’ll probably want to run production code on one of the alternative servers. Let’s look briefly at the available servers.

WEBrick

WEBrick, the default server for Rails, is written entirely in Ruby. It supports the standards you’ll need—HTTP for communications, HTML for web pages, and RHTML for embedding Ruby code into web pages for dynamic content. WEBrick has some important advantages:

  • It comes with Ruby, so it’s free and is always available for your use or for packaging with your projects.

  • It’s built into Rails, so you don’t have to go through any special effort for integration.

  • It can make direct calls to your Rails application because they are both written in Ruby.

  • It’s simple to use.

Apache

Although WEBrick is the most convenient choice, it’s not the most scalable or flexible choice. The Apache web server is the most widely deployed web server in the world. You can choose from an incredible array of plug-ins to run dozens of programming languages or serve other kinds of dynamic content. Apache scales well, with outstanding caching plug-ins and good support for load balancers and sprayers (machines that efficiently spread requests across multiple web servers). If you’re looking for a safe solution, look no further than the Apache web server.

lighttpd

Apache is a good general-purpose web server, but it’s not the most specialized server. lighttpd is a lightweight web server that’s built for one thing: speed. It serves static content such as HTML web pages and images very quickly, and supports applications through an application interface called FastCGI. lighttpd does not have nearly as many flexible plug-ins or the marketing clout of the Apache web server, but if you’re looking for a specialized server to serve static content and Rails applications quickly, lighttpd could be your answer. It’s fairly young, but it has a great reputation for speed among Rails enthusiasts.

Mongrel

Although Apache and lighttpd are very fast and scalable production servers, configuring them to serve your Rails application can sometimes be challenging, and it is never as simple as WEBrick. A new web server, Mongrel, may just change all of that. Mongrel combines the advantages of WEBrick (because it’s written in Ruby) and lighttpd (because it’s written for speed). This combination could make Mongrel an excellent choice for both development and production. It’s even younger than lighttpd, but it looks so promising that it has already received backing from a major corporation to speed its development.

Other web servers

Theoretically, any web server that supports CGI can serve a Rails application. Unfortunately, CGI with Rails is dead slow, so it is really not suitable for production. However, if you are running in a specialized environment that has its own web server, you can probably get it to serve your Rails application using the FastCGI or SCGI interfaces. Do a web search first because it’s very likely that someone else has already done it and posted instructions. For example, if you must deploy your Rails application on Microsoft’s IIS, you will find that many developers have done this already, and the instructions are easy to find. You’ll probably see other web servers rapidly move to support Rails.

Now that your server is up, it’s time to write some code. We’ll focus on simple controllers and views in the rest of this chapter.

Creating a Controller

You’ve seen that Rails organizes applications into pieces with a model, view, and controller. We’ll start with the controller. Use the generate script (see the sidebar "script/generate“) to create a controller. We’ll specify the type of object to create first and then the name of the new controller. Type:

> ruby script/generate controller Greeting
      exists  app/controllers 
/
      exists  app/helpers/
      create  app/views/greeting
      exists  test/functional/
      create  app/controllers/greeting_controller.rb
      create  test/functional/greeting_controller_test.rb
      create  app/helpers/greeting_helper.rb

You might not have expected to see so much activity. Rails created your expected controller--greeting_controller.rb. But you also got a few other files as well:

application.rb

There is not yet a controller for the whole application, so Rails created this one. It will come in handy later as a place to anchor application-wide concerns, such as security.

views/greeting

Rails knows that controllers and views usually come in pairs, so it created a directory called views/greeting.

greeting_controller_test.rb

Rails also created a test for your new controller because most Rails developers build automated unit tests to make it easy to build in and maintain quality.

greeting_helper.rb

Rails helpers provide a convenient place to prevent repetition or tedious code from cluttering your views.

Ruby developers created Rails to solve their own problems before generalizing and releasing the tool to solve your problems too. You’re seeing an example of excellent experience-based design. Early Rails users noticed that right after creating a controller, they usually needed additional layers of the application, and so they modified the controller generator to save themselves a few keystrokes. Rails inventors eat their own dog food.

Running the Controller

Let’s run the application; point your browser to http://127.0.0.1:3000/greeting. You’ll get an error message telling you that index is an unknown action. Let’s find out why. Edit the new controller at the path app/controller/greeting_controller.rb:

    class GreetingController < ApplicationController
    end

You haven’t told Rails to do anything yet, so getting some kind of error seems logical. Still, you’ll need a little more background before you can fix that problem. Figure 1-2 shows how Rails controllers work.

Rails’ model-view-controller flow
Figure 1-2. Rails’ model-view-controller flow

Rails uses the Action Pack framework to manage controllers. Web browsers communicate with servers by sending requests over the HTTP protocol. For our greeting application, the request was simply to load a URL. The first part of a URL identifies a machine, and the second part identifies a web resource. In the Action Pack, the resource has at least three parts: a controller, some action to perform on a controller, and an identifier of a resource. Actions map directly onto controller methods. For example, for this URL:

http://www.spatulas.com/shopping_cart/total/45

http://www.spatulas.com/ identifies the web server, shopping_cart identifies the controller, total identifies the action, and 45 identifies a resource—probably a cart. The web server routes incoming requests to a Ruby script in the Rails framework called the dispatcher. Rails has one dispatcher per web server. Next, the Rails dispatcher parses the URL and invokes the appropriate action on the appropriate controller. The controller action may then call the model and ultimately invokes a view.

By default, if you call a controller without specifying an action, Rails calls the index action. Now, the error makes more sense. When we specified the URL app/controller/greeting, we supplied a controller without an action, so Rails defaulted to a nonexistent index action. You can fix the problem by adding a method called index to GreetingController. Let’s keep things simple by making the index method print out HTML directly, as shown in Example 1-1.

Example 1-1. Rails controller displaying a greeting
class GreetingController < ApplicationController
   def index
      render :text => "<h1>Welcome to your first Rails application<h1>"
   end
end

Save your code and reload your browser—you’ll get the web page in Figure 1-3. Even though you changed some code, you didn’t have to restart the server, redeploy your application, or do anything but reload your browser. This quick turnaround time, called a rapid feedback loop, is a hallmark of Ruby and Rails. Often, new Rails developers point to the rapid feedback loop as the feature that affected their productivity more than anything else.

Rendering text from a controller
Figure 1-3. Rendering text from a controller

Building a View

You now have a controller that renders text, but this design can take you only so far. If you want to follow Rails MVC conventions, you should render text in a separate view instead of a controller. The sloppy design is easy enough to fix. Instead of printing raw text in a controller, render it in a view. As with many web frameworks, Rails can use a template strategy for the view. For Rails, a template is simply an HTML page with Ruby code mixed in. The Ruby code executes on the server, adding dynamic content to the HTML page.

With Rails, you can generate the view and some helpers that the view will need. Type the generate command to generate a new controller, greeting, with a view, index. (You do this to tie the view and controller together.) When it asks you whether to overwrite the controller, type n for no:

    > ruby script/generate controller Greeting index
      exists  app/controllers/

      exists  app/helpers/
      exists  app/views/greeting
      exists  test/functional/
overwrite app/controllers/greeting_controller.rb? [Ynaq] n
        skip  app/controllers/greeting_controller.rb
overwrite test/functional/greeting_controller_test.rb? [Ynaq] a
forcing controller
       force  test/functional/greeting_controller_test.rb
       force  app/helpers/greeting_helper.rb
      create  app/views/greeting/index.rhtml

The generator created the view, index.rhtml, with helper and test files. Keep the index method, so Action Pack can find the action, but take the rest of the code out of the index method:

class GreetingController < ApplicationController
   def index
   end
end

Unlike most MVC frameworks, you didn’t specify a view. If your controller doesn’t render anything, Rails uses naming conventions to find the right view. The controller’s name determines the view’s directory, and the controller’s method name determines the name of the view. In this case, Action Pack fires the view in app/view/greeting/index.rhtml. You didn’t have to edit any XML files or type any additional code. You provide consistent naming conventions, and Rails infers your intent.

Now, edit the view. You’ll find this data:

<h1>Greeting#index</h1>
<p>Find me in app/views/greeting/index.rhtml</p>

Reload your browser to see the previous message in HTML. Rails tells you where to find the file, should you ever render an unimplemented view. Rails is full of nice finishing touches like these.

Tying the Controller to the View

In MVC, the view usually renders model data provided by the controller. Let’s set an instance variable in the controller and render it in the view. First, add an instance variable called @welcome_message to the controller:

class GreetingController < ApplicationController
   def index
      @welcome_message = "Welcome to your first Rails application"
   end
end

Now, display the new message in the view by adding a Ruby expression between <%= and %> tags. Rails renders the value of the expression within these tags, just as if the value of the expression had been printed in place. Here’s a view that prints your welcome message as a level one heading:

<h1><%= @welcome_message %></h1>

Reload. You’ll see the same output you got in Example 1-1, though the structure of the application is different. In Example 1-1, you rendered your view within the controller. Here, you built an RHTML template. Your HTML tags provided static structure and style, and your Ruby code provided dynamic content; in this case, a variable set within the controller.

Expressions and Scriptlets

When you’re embedding Ruby code, you’ve got two options. Scriptlets are Ruby code, placed between <% and %> tags. Scriptlets rely on side effects, or the output of the Ruby code. Expressions are Ruby expressions placed between <%= and %> tags. The expression presents the value returned by the Ruby code.

You can experiment with the interaction between the controller and view. We’ve changed the controller and view for greeting to show a few examples of expressions and scriptlets in action. First, we’ll set a few values in the controller:

class GreetingController < ApplicationController
  def index
    @age=8
    @table={"headings" => ["addend", "addend", "sum"],
            "body"     => [[1, 1, 2], [1, 2, 3], [ 1, 3, 4]]
           }
  end
end

Next, here’s the view showing expressions and scriptlets, with both interacting with values set in the controller:

<h1>Simple expression</h1>
<p>Tommy is <%= @age %> years old.</p>

Now, display the value of the instance variable @age, which was set in the controller:

<h1>Iteration using scriptlets</h1>
<% for i in 1..5 %>
  <p>Heading number <%= i %> </p>
<% end %>

Iterate with a scriptlet and show the current count with an expression:

<h1>A simple table</h1>

<table>
  <tr>
    <% @table["headings"].each do |head| %>
      <td>
        <b><%= head %></b>
      </td>
    <% end %>
  </tr>

  <% @table["body"].each do |row| %>
    <tr>
      <% row.each do |col| %>
        <td>
           <%= col %>
        </td>
      <% end %>
    </tr>
  <% end %>

</table>

Finally, use both techniques to display the contents of @table.

You’ll get the results shown in Figure 1-5.

Results of embedded scriptlets and expressions
Figure 1-5. Results of embedded scriptlets and expressions

Under the Hood

As shown earlier, each time you submit a URL, you’re creating an HTTP request, which fires a controller action. Any MVC framework designer needs to decide between reusing the same controller for each request and creating a new controller copy per request. Rails does the latter strategy, which it calls request scope. Each HTTP request results in a new controller instance, meaning that you’ll also get a new set of instance variables for each HTTP request. That’s going to affect you in at least two different ways:

  • On the plus side, you don’t need to worry about threading in your controllers because each request gets a private copy of the controller’s instance data.

  • On the minus side, it will be harder for you to share instance data between requests. Specifically, if you set instance variables in one controller action method, don’t expect to be able to use them in later HTTP requests. You’ll need to share them in a session.

What’s Next?

You’ve created a Rails project. You’ve created a controller and invoked it from a browser. You’ve also created a view and learned how views can interact with controllers and with the Ruby language. That’s a good foundation, but you’ve seen only two pieces of the model-view-controller design pattern. In the next chapter, you’ll learn how models work. We’ll create a database schema and let Rails use the schema to generate our model for us. We’ll then use a Rails framework to help manage relationships between the different parts of the application.



[*] The number 500,000 is actually a conservative estimate. Download statistics for a popular delivery vehicle, called gems, make it easy to track the number of Rails distributions by gems, but many other distributions exist, such as the Locomotive distribution on Mac OS X. The real download statistics could easily be twice this number.

[*] For example, Hibernate supports three kinds of inheritance mapping, but Rails supports only single-table inheritance. Hibernate supports composite keys, but Rails is much more limited.

[] Rails also uses code generation but relies much more on metaprogramming for the heavy lifting.

[*] If you want to code along with us, make sure you’ve installed Ruby and gems. Appendix A contains detailed installation instructions.

Get Ruby on Rails: Up and Running now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.