It’s time to meet the key player in Rails applications. Controllers are the components that determine how to respond to user requests and coordinate responses. They’re at the heart of what many people think of as “the program” in your Rails applications, though in many ways they’re more of a switchboard. They connect the different pieces that do the heavy lifting, providing a focal point for application development. The model is the foundation of your application’s data structures, which will let you get information into and out of your databases.
Demonstrating controllers without getting tangled in all of Rails’ other components is difficult, so for an initial tour, the application will be incredibly simple. (You can see the first version of it in ch04/guestbook001.) Guestbooks were a common (if kind of annoying) feature on early websites, letting visitors “sign in” so that the site could tell who’d been there. (The idea has since evolved into much more sophisticated messaging, like Facebook’s “wall.”)
To get started, create a new Rails application, as we did in Chapter 1. If you’re working from the command line, type:
Rails will create the usual pile of files and folders. Next, you’ll want to change to the guestbook directory and create a controller:
ruby script/generate controller entriesexists app/controllers/ exists app/helpers/ create app/views/entry exists test/functional/ create app/controllers/entries_controller.rb create test/functional/entries_controller_test.rb create app/helpers/entries_helper.rb
(In Heroku, you can just create a new application, then choose
Generate from the gear menu, and enter
If you then look at app/controllers/entries_controller.rb, which is the main file we’ll work with here, you’ll find:
class EntriesController < ApplicationController end
This doesn’t do very much. However, there’s an important
relationship in that first line. Your
EntriesController inherits from
lives in app/controllers/application.rb, and it also
doesn’t do very much initially, but if you ever need to add
functionality that is shared by all of the controllers in your
application, you can put it into the
To make this controller actually do something, we’ll add a method.
For right now, we’ll call it
creating the very simple object in Example 4-1.
Example 4-1. Adding an initial method to an empty controller
class EntriesController < ApplicationController
We’ll also need a view, so that Rails has something it can present to visitors. You can create a sign_in.html.erb file in the app/views/entry/ directory, and then edit it, as shown in Example 4-2.
You may remember from Chapter 2 that you could have had Rails create a method in the controller as well as a basic view at the same time that it created the controller, by typing:
ruby script/generate controller entries sign_in
You can work either way, letting Rails generate as much (or as little) code as you like.
Example 4-2. A view that lets users see a message and enter their name
<html> <head><title>Hello <%=h @name %></title></head> <body> <h1>Hello <%=h @name %></h1>
<% form_tag :action => 'sign_in' do %><p>Enter your name:
<%= text_field_tag 'visitor_name', @name %></p>
<%= submit_tag 'Sign in' %>
<% end %></body> </html>
Example 4-2 has a lot of new pieces to it because it’s using helper methods to create a basic form. Helper methods take arguments and return text, which in this case is HTML that helps build your form. The following particular helpers are built into Rails, but you can also create your own:
method takes two parameters and uses them to create a
form field on the page. The first,
visitor_name, is the identifier that the
form will use to describe the field data it sends back to the
controller, while the second is default text that the field will
contain. If the user has filled out this form previously, and our
controller populates the
variable, it will list the user’s name. Otherwise, it will be
If you start up the server and visit http://localhost:3000/entries/sign_in (or, in Heroku or Instant Rails, the name of your server followed by /entries/sign_in), you’ll see a simple form like Figure 4-1.
If you get an error message about a database not being found, you may want to explore the option described at the end of Chapter 1 in “Turning Off Databases, For Now.” You’ll need to turn them on again later in this chapter, though.
Now that we have a way to send data to our controller, it’s time to update the controller so that it does something with that information. In this very simple case, it just means adding a line, as shown in Example 4-3.
Example 4-3. Making the sign_in method do something
class EntriesController < ApplicationController def sign_in
@name = params[:visitor_name]end end
The extra line gets the
visitor_name parameter from the request header
sent back by the client and puts it into
@name. (If there wasn’t a
visitor_name parameter, as would be normal the
first time this page is loaded,
will just be blank.)
If you enter a name into the form, you’ll now get a pretty basic hello message back as shown in Figure 4-2. The name will also be sitting in the form field for another round of greetings.
If, instead of Figure 4-2, you get a
strange error message about “wrong number of arguments (1 for 0),”
check your code carefully. You’ve probably added a space between
[, which produces a syntax error whose
description isn’t exactly clear.
This isn’t incredibly exciting, admittedly, but it’s a start. The controller is now receiving information from the user and passing it to a view, which can then pass more information.
There is one other minor point worth examining before we move on,
though: how did Rails convert the http://localhost:3000/entries/sign_in URL into a call to
sign_in method of the
entry controller? If you look in the config directory of your application, you’ll
find the routes.rb file, which contains two default rules for choosing what
gets called when a request comes in:
map.connect ':controller/:action/:id' map.connect ':controller/:action/:id.:format'
In this case,
entry mapped to
sign_in mapped to
:action. Rails used this simple mapping to
decide what to call. We don’t have an
:id or a
:format—yet. (And as Chapter 2 demonstrated, if there hadn’t been an
:action, Rails would have defaulted
index.) Figure 4-3 shows how Rails
breaks down a URL to decide where to go.