O'Reilly logo

Rails: Up and Running, 2nd Edition by Curt Hibbs, Lance Carlson, Bruce Tate

Stay ahead with the world's most comprehensive technology and business learning platform.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

Start Free Trial

No credit card required

Chapter 1. Zero to Sixty: Introducing Rails

When we wrote the first version of this book, Rails was just starting to ramp up as a framework. Now, the exploding web development platform is working its way into the mainstream. Companies like Twitter have bet on Rails and won big, and others have tried Rails and crashed hard. You should be comfortable that you’re entering this ecosystem not as a pioneer, but as part of a much greater wave that’s sweeping through the whole computing profession. If you read the first edition, you’ll notice that we’re not selling the framework quite so hard. In all honesty, we don’t have to. Let’s lay the basic foundation so we can get to work.

Rails is a framework for building database-backed web applications. Based on the Ruby programming language, Rails is best for applications that need to be developed quickly without sacrificing a clean structure that can also be well-maintained. Ruby is interpreted, but it’s fast enough to attack websites with all but the most demanding performance characteristics. And it’s tremendously popular. That popularity means you can find what you need to build projects in Rails.

Since the first edition of this book was released, the Rails core team released milestone versions 1.1, 1.2, 2.0, and now 2.1. Today, you can find excellent hosting from dozens of vendors depending on how much management you’re willing to do. And technical officers like me (Bruce Tate) are bringing Rails into the enterprise to run our core businesses. The Rails framework has since led to rapid investment in the Ruby programming language, too, including evolving implementations on the Java Virtual Machine, the Microsoft Common Language Runtime, and two emerging Ruby virtual machines. Rails is also redefining web development frameworks in other languages as well. Java, PHP, Python, Lisp, Groovy, and Perl each have more than one Rails-like framework. The Rails convention-based approach is overtaking standard configuration-based approaches just about everywhere.

In this book, we will walk you through everything you need to get a simple application up and running. We promise to move slowly enough that you can absorb the concepts, but quickly enough so that you will have a working application after following along for a few hours. Let’s get started.

Putting Rails into Action

We’re going to blow through installation quickly because installation details can change with Rails itself and the individual platforms that support it. The best place to go, regardless of your platform, is the Rails wiki at http://wiki.rubyonrails.org/rails/pages/GettingStartedWithRails. We’ll give you a condensed version here: you’ll install Ruby, Rails, and then your database. First, install Ruby. If you’re running OS X, chances are good that Ruby is already there, but older versions will need an upgrade. If you’re running Windows, there are some good one-click installers that you can use such as the Ruby one-click installer at http://rubyinstaller.rubyforge.org. For now, just install Ruby, and we’ll walk you through the rest.

Once you’ve installed Ruby, you could manually install all of the components for Rails, but Ruby has a packaging and deployment feature named gems. The gem installer accesses a central repository and downloads an application unit, called a gem, and all its dependencies. If you haven’t done so, install Rails with this command:[1]

sudo gem install rails --include-dependencies  -v 2.1

The command for installing Ruby components on all platforms is the same: gem install. The permissions required will vary from platform to platform. On OS X, sudo elevates your permissions for this command to superuser status. You’ll want to omit the sudo portion of this command on Windows. If things go well, you’ll see a list of a bunch of different gems fly by. These are Rails and all of the dependencies that Rails requires. That’s it—Rails is installed. There’s one caveat: you also need to install the database support for your given database. In this book, we’re going to use SQLite, but you can use any database engine supported by Rails. On Unix, chances are SQLite is already installed. On Windows, you’ll need to pull down the SQLite DLL and command-line client. For more details, go to http://wiki.rubyonrails.com/rails/pages/HowtoUseSQLite. With Ruby, Rails, and a database, you’re ready to create a 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/functional
      create  test/integration
      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. Rails creates folders that you’ll use to hold the model, view, and controller portions of your application code, different kinds of test cases, database configuration, and third-party libraries that you might choose to install later. All Rails projects will use this same organization with a few slight variations. You’ll run just about all of your Rails scripts from your new project directory. Go to your project directory with cd chapter-1. In the next section, we’ll take a look at the organization of your project in more detail.

Organization

The directories created during installation provide a place for your application 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 directory has your Rails application. You’ll spend most of your development time working on files in this directory. app has subdirectories that hold the view (views and helpers), controller (controllers), and the backend business logic (models).

config

This directory contains the small amount of configuration code that your application will need. Your database configuration will go in database.yml. Common environmental configuration, such as the configuration of any mail server your application needs, will go in environment.rb. Rules for your URLs that route incoming web requests go in routes.rb. You can also specifically tailor the behavior of the three Rails environments for test (environments/test.rb), development (environments/development.rb), and production (environments/production.rb) with files found in the environments directory.

db

Your Rails application will have model objects that access relational database tables. Files that describe the schema (schema.rb) go in this directory. Migrations, Ruby scripts that make it easy to code changes in your database schema, go in the db/migrations 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 common Rails libraries here, unless they explicitly belong elsewhere (such as vendor libraries). For example, common authentication libraries might go in this directory.

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). Some Rails caching solutions also create .html files that go in the public directory.

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 (generate) and delete (destroy) code and launch the web server (server). Other scripts launch a console (console) for managing your application and debugging or installing and removing plug-ins (plugin). You’ll learn much more about using many of 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), integration tests (integration), fixtures (fixtures), and functional tests (functional). We’ll cover a brief introduction to 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, plug-ins, 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.

The Web Server

Now that we’ve got a project, let’s start the web server. If you haven’t already done so, type cd chapter-1 to switch to your project directory. Use the script/server script to start an instance of the Mongrel server configured for development. If you’re running Windows, each time you see a command that’s prefaced with the script directory, preface the call instead with ruby, using forward or backward slashes. If you’re using most other platforms, you can omit the ruby keyword. From here on out, we’ll skip the ruby part of the command. Type script/server now:

$ script/server

=> Booting Mongrel (use 'script/server webrick' to force WEBrick)
=> Rails application starting on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
** Starting Mongrel listening at 0.0.0.0:3000
** Starting Rails with development environment...
** Rails loaded.
** Loading any Rails specific GemPlugins
** Signals ready.  TERM => stop.  USR2 => restart.  INT => stop (no restart).
** Rails signals registered.  HUP => reload (without restart).  It might not work well.
** Mongrel 1.1.1 available at 0.0.0.0:3000
** Use CTRL-C to stop.

Notice these details:

  • The server started on port 3000. You can change the port number and other startup details with command-line options. See the sidebar “Configuring the Server” for more configuration options.

  • We started an instance of Mongrel, the default web server. You can configure Rails to start many kinds of web servers.

  • 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 on Windows because it allows you to use the tab completion feature in the MS-DOS command prompt.

Point your browser to 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 already set up the build environment, typed a few words, and verified that the server is running. In the development environment, you’ll normally leave the server up, rebooting only to make major configuration changes for things such as new gems or a changed database configuration.

Choosing a Server

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

Apache

Although WEBrick is the most convenient choice, it’s not the most scalable or flexible. 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 (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.

nginx

Apache is a good general-purpose web server, but it’s not the most specialized one. nginx has replaced lighttpd in the Rails community as the lightweight web server that’s built for one thing: speed. It serves static content such as HTML web pages and images very quickly, and it supports applications through Mongrel and Mongrel Cluster. nginx 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, nginx 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. Mongrel changes all of that. Mongrel combines the advantages of WEBrick (because it’s written in Ruby) and nginx (because it’s written for speed and clusters well). This combination could make Mongrel an excellent choice for development and production. You can quickly cluster Mongrel with MongrelCluster. Be careful, though—Mongrel does not serve static content very quickly. For demanding deployments, you’ll want to combine Mongrel with one of the web servers mentioned above, likely Apache or nginx.

WEBrick

WEBrick, once the default development server for Rails, is written entirely in Ruby. It supports the standards you’ll need—HTTP for communications, HTML for web pages, and ERb for embedding Ruby code into web pages for dynamic content. WEBrick is generally not used anymore, even in pure development mode. Mongrel has taken its place.

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. You’ll probably see other web servers rapidly move to support Rails. You can also find plenty of information on lighttpd with FastCGI. Deploying Rails applications is far beyond the scope of this book.

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 to create a controller. In Chapter 2, we’ll talk more about the generator for controllers. For now, 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 render views, 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 set repetitive or complicated code that might otherwise reside in your views. By separating this code, you can keep your views clean and simple.

Rails creators built the framework to first solve their own problems. As a result, you see plenty of practical experience in the framework. The generators are a great example of that practical experience in action. You get a combination of all the application files that you’ll need to build the controller.

Mapping params

Let’s discuss what has happened so far. When the web server calls Rails, the router matches a URL to the route. Before invoking a controller, Rails builds a hash of params based on the chosen route. The router also adds any additional URL parameters to the params hash. You can easily see what’s in the params hash by directly rendering some text. Add the following code to app/controllers/greeting_controller.rb to see the params:

class GreetingController < ApplicationController

  def index
  end
  
  def show
    render :text => params.inspect
  end
end

Now, point your browser to http://localhost:3000/greeting/show. You should see the text {"action"=>"show", "controller"=>"greeting"}. The Rails router set the action and controller keys. Try a more complicated URL, as shown in Example 1-1.

Example 1-1. Rails builds a hash from a URL
For URL: http://localhost:3000/greeting/show/1?key=value&another_key=value
The hash is: {"action"=>"show", 
              "id"=>"1", 
              "controller"=>"greeting", 
              "another_key"=>"value", 
              "key"=>"value"}

Much of the time, in Rails, you’re dealing with URLs that amount to nothing more than a bunch of key/value pairs. On the URL, these are query strings. In Ruby, they’re a hash. Don’t let these hashes be a mystery. The routes table found in config/routes.rb will tell you exactly how Rails will carve the URL into a convenient list of parameters. You’ll see much more in the next chapter, but for now, it’s time to build a view.

Building a View

You now have a controller that renders text, but this design can take you only so far. Ideally, you’d like to separate the HTML in the view from your business logic in your controllers and models. The sloppy design is easy enough to fix. If you want to follow Rails MVC conventions, you should render text in a separate view instead of from your controller. Instead of the render command in the greeting controller, you can render the text in a Rails view. As with many web frameworks, Rails can use a template strategy for the view. A template is simply an HTML page with Ruby code mixed in. A Ruby engine called ERb interprets the template on the server, adding dynamic content to your page. That page will usually be written in HTML, but you can design templates for XML pages or email, too.

Rails documentation for the controller
Figure 1-2. Rails documentation for the controller

With Rails, you can generate an empty view and some helpers that the view will need along with your controller. Type the script/destroy controller greeting command to destroy the previous controller:

    $ ruby script/destroy controller greeting

          rm  app/helpers/greeting_helper.rb
          rm  test/functional/greeting_controller_test.rb
          rm  app/controllers/greeting_controller.rb
       rmdir  test/functional
    notempty  test
       rmdir  app/views/greeting
    notempty  app/views
    notempty  app
    notempty  app/helpers
    notempty  app
    notempty  app/controllers
    notempty  app

Next, type script/generate controller greeting index to generate a controller with the index action and index view:

    $ ruby script/generate controller greeting index

      exists  app/controllers/
      exists  app/helpers/
      create  app/views/greeting
      create  test/functional/
      create  app/controllers/greeting_controller.rb
      create  test/functional/greeting_controller_test.rb
      create  app/helpers/greeting_helper.rb
      create  app/views/greeting/index.html.erb

See also Figure 1-3.

Rails documentation for the controller
Figure 1-3. Rails documentation for the controller

The generator created the view, index.html.erb, with helper and test files. From the output, you can see that the generator created a few directories, a controller called greeting_controller.rb, a helper called greeting_helper.rb, and a test called greeting_controller_test.rb. Take a look at the new index method in controller, called app/controllers/greeting_controller.rb:

class GreetingController < ApplicationController

   def index
   end
end

This controller example uses Action Pack, the Rails framework responsible for implementing the view and controller parts of Rails. Unlike most MVC frameworks, your index method didn’t specify a view. If your controller doesn’t explicitly call render, Rails uses naming conventions to decide which view to render. The controller’s name determines the view’s directory, and the action name determines the name of the view. An action is a method on a controller. In this case, Action Pack fires the view in app/views/greeting/index.html.erb. You didn’t have to edit any XML files or type any additional code to wire the controller to the view. You just allowed Rails to provide consistent naming conventions and infer your intent from there.

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

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

Point your browser to http://localhost:3000/greetings/index to see the previous message in HTML. Rails tells you where to find the file, should you ever render an unimplemented view. This empty file awaits an implementation.

Tying Controller Data to the View

In MVC, the view needs to render any data the controller provides. That data may come from model logic, the session, or any other source. Regardless of where the data comes from, in Rails, instance variables in the controller are available to the view. Let’s try setting a variable called @welcome_message in 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 the <%= 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 output from the view, with the message you created in the index method. In Example 1-1, you rendered your view within the controller. Here, you built an HTML.ERB 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. That’s MVC.

Expressions and Scriptlets

When you’re embedding Ruby code within a view template, you’ve got two options. Scriptlets are Ruby code placed between the <% and %> tags. Scriptlets run Ruby code without printing the results. You will often use a scriptlet to loop through the elements of a Ruby array, for example. Expressions are Ruby expressions placed between the <%= and %> tags. An expression presents the value returned by the Ruby code. You will use an expression to place the result of any Ruby code in a web page, just as if you’d printed the code there.

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 views/index.html.erb view showing expressions and scriptlets, both of which interact 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-4.

Results of embedded scriptlets and expressions
Figure 1-4. 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 uses 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, and Rails will take more resources. Specifically, if you set instance variables in one controller action method, don’t expect to be able to use them in later HTTP requests, even if you simply redirect your request. You’ll need to share them in a session, a cookie, or the URL.

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. The next chapter will show you a more extensive look at views and controllers. You’ll use what you know, and some new tricks, to scaffold together a pretty sophisticated application that you’ll use as the foundation for the rest of the book. Let’s code.



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

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, interactive tutorials, and more.

Start Free Trial

No credit card required