Now that we have a working User model, it’s time to add an ability few websites can live without: letting users sign up. We’ll use an HTML form to submit user signup information to our application (Section 7.2), which will then be used to create a new user and save its attributes to the database (Section 7.4). At the end of the signup process, it’s important to render a profile page with the newly created user’s information, so we’ll begin by making a page for showing users, which will serve as the first step toward implementing the REST architecture for users (Section 2.2.2). Along the way, we’ll build on our work in Section 5.3.4 to write succinct and expressive integration tests.
In this chapter, we’ll rely on the User model validations from Chapter 6 to increase the odds of new users having valid email addresses. In Chapter 10, we’ll make sure of email validity by adding a separate account activation step to user signup.
In this section, we’ll take the first steps toward the final profile by making a page to display a user’s name and profile photo, as indicated by the mockup in Figure 7.1.1 Our eventual goal for the user profile pages is to show the user’s profile image, basic user data, and a list of microposts, as mocked up in Figure 7.2.2 (Figure 7.2 has our first example of lorem ipsum text, which has a fascinating story that you should definitely read about some time.) We’ll complete this task, and with it the sample application, in Chapter 12.
If you’re following along with version control, make a topic branch as usual:
$ git checkout master
$ git checkout -b sign-up


The profiles in this section will be the first truly dynamic pages in our application. Although the view will exist as a single page of code, each profile will be customized using information retrieved from the application’s database. As preparation for adding dynamic pages to our sample application, now is a good time to add some debug information to our site layout (Listing 7.1). This displays some useful information about each page using the built-in debug method and params variable (which we’ll learn more about in Section 7.1.2).
app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
.
.
.
<body>
<%= render 'layouts/header' %>
<div class="container">
<%= yield %>
<%= render 'layouts/footer' %>
<%= debug(params) if Rails.env.development? %>
</div>
</body>
</html>
Since we don’t want to display debug information to users of a deployed application, Listing 7.1 uses
if Rails.env.development?
to restrict the debug information to the development environment, which is one of three environments defined by default in Rails (Box 7.1).3 In particular, Rails.env.development? is true only in a development environment, so the embedded Ruby
<%= debug(params) if Rails.env.development? %>
won’t be inserted into production applications or tests. (Inserting the debug information into tests probably wouldn’t do any harm, but it probably wouldn’t do any good, either, so it’s best to restrict the debug display to development only.)
Rails comes equipped with three environments: test, development, and production. The default environment for the Rails console is development:
$ rails console Loading development environment >> Rails.env => "development" >> Rails.env.development? => true >> Rails.env.test? => false
As you can see, Rails provides a Rails object with an env attribute and associated environment boolean methods, so that, for example, Rails.env.test? returns true in a test environment and false otherwise.
If you ever need to run a console in a different environment (to debug a test, for example), you can pass the environment as a parameter to the console script:
$ rails console test Loading test environment >> Rails.env => "test" >> Rails.env.test? => true
As with the console, development is the default environment for the Rails server, but you can also run it in a different environment:
$ rails server --environment production
If you view your app running in production, it won’t work without a production database, which we can create by running rake db:migrate in production:
$ bundle exec rake db:migrate RAILS_ENV=production
(I find it confusing that the console, server, and migrate commands specify non-default environments in three mutually incompatible ways, which is why I bothered showing all three.)
By the way, if you have deployed your sample app to Heroku, you can see its environment using heroku run console:
$ heroku run console >> Rails.env => "production" >> Rails.env.production? => true
Naturally, since Heroku is a platform for production sites, it runs each application in a production environment.
To make the debug output look nice, we’ll add some rules to the custom stylesheet created in Chapter 5, as shown in Listing 7.2.
app/assets/stylesheets/custom.css.scss
@import "bootstrap-sprockets";
@import "bootstrap";
/* mixins, variables, etc. */
$gray-medium-light: #eaeaea;
@mixin box_sizing {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
.
.
.
/* miscellaneous */
.debug_dump {
clear: both;
float: left;
width: 100%;
margin-top: 45px;
@include box_sizing;
}
This introduces the Sass mixin facility, in this case called box_sizing. A mixin allows a group of CSS rules to be packaged up and used for multiple elements, converting
.debug_dump {
.
.
.
@include box_sizing;
}
to
.debug_dump {
.
.
.
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
We’ll put this mixin to use again in Section 7.2.1. The result in the case of the debug box is shown in Figure 7.3.

The debug output in Figure 7.3 gives potentially useful information about the page being rendered:
---
controller: static_pages
action: home
This is a YAML4 representation of params, which is basically a hash, and in this case identifies the controller and action for the page. We’ll see another example in Section 7.1.2.
In order to make a user profile page, we need to have a user in the database, which introduces a chicken-and-egg problem: how can the site have a user before there is a working signup page? Happily, this problem has already been solved: in Section 6.3.4, we created a User record by hand using the Rails console, so there should be one user in the database:
$ rails console
>> User.count
=> 1
>> User.first
=> #<User id: 1, name: "Michael Hartl", email: "mhartl@example.com",
created_at: "2014-08-29 02:58:28", updated_at: "2014-08-29 02:58:28",
password_digest: "$2a$10$YmQTuuDNOszvu5yi7auOC.F4G//FGhyQSWCpghqRWQW...">
(If you don’t currently have a user in your database, you should visit Section 6.3.4 now and complete it before proceeding.) We see from the console output above that the user has id 1, and our goal now is to make a page to display this user’s information. We’ll follow the conventions of the REST architecture favored in Rails applications (Box 2.2), which means representing data as resources that can be created, shown, updated, or destroyed—four actions corresponding to the four fundamental operations POST, GET, PATCH, and DELETE defined by the HTTP standard (Box 3.2).
When following REST principles, resources are typically referenced using the resource name and a unique identifier. What this means in the context of users—which we’re now thinking of as a Users resource—is that we should view the user with id 1 by issuing a GET request to the URL /users/1. Here the show action is implicit in the type of request—when Rails’ REST features are activated, GET requests are automatically handled by the show action.
We saw in Section 2.2.1 that the page for a user with id 1 has URL /users/1. Unfortunately, visiting that URL right now just gives an error, as seen in the server log (Figure 7.4).

We can get the routing for /users/1 to work by adding a single line to our routes file (config/routes.rb):
resources :users
The result appears in Listing 7.3.
config/routes.rb
Rails.application.routes.draw do
root 'static_pages#home'
get 'help' => 'static_pages#help'
get 'about' => 'static_pages#about'
get 'contact' => 'static_pages#contact'
get 'signup' => 'users#new'
resources :users
end
Although our immediate motivation is making a page to show users, the single line resources :users doesn’t just add a working /users/1 URL; it endows our sample application with all the actions needed for a RESTful Users resource,5 along with a large number of named routes (Section 5.3.3) for generating user URLs. The resulting correspondence of URLs, actions, and named routes is shown in Table 7.1. (Compare to Table 2.2.) Over the course of the next three chapters, we’ll cover all of the other entries in Table 7.1 as we fill in all the actions necessary to make Users a fully RESTful resource.
| HTTP request | URL | Action | Named route | Purpose |
GET |
/users | index |
users_path |
page to list all users |
GET |
/users/1 | show |
user_path(user) |
page to show user |
GET |
/users/new | new |
new_user_path |
page to make a new user (signup) |
POST |
/users | create |
users_path |
create a new user |
GET |
/users/1/edit | edit |
edit_user_path(user) |
page to edit user with id 1 |
PATCH |
/users/1 | update |
user_path(user) |
update user |
DELETE |
/users/1 | destroy |
user_path(user) |
delete user |
With the code in Listing 7.3, the routing works, but there’s still no page there (Figure 7.5). To fix this, we’ll begin with a minimalist version of the profile page, which we’ll flesh out in Section 7.1.4.

We’ll use the standard Rails location for showing a user, which is app/views/users/show.html.erb. Unlike the new.html.erb view, which we created with the generator in Listing 5.29, the show.html.erb file doesn’t currently exist, so you’ll have to create it by hand, and then fill it with the content shown in Listing 7.4.
app/views/users/show.html.erb
<%= @user.name %>, <%= @user.email %>
This view uses embedded Ruby to display the user’s name and email address, assuming the existence of an instance variable called @user. Of course, eventually the real user show page will look very different (and won’t display the email address publicly).
In order to get the user show view to work, we need to define an @user variable in the corresponding show action in the Users controller. As you might expect, we use the find method on the User model (Section 6.1.4) to retrieve the user from the database, as shown in Listing 7.5.
show action. app/controllers/users_controller.rb
class UsersController < ApplicationController
def show
@user = User.find(params[:id])
end
def new
end
end
Here we’ve used params to retrieve the user id. When we make the appropriate request to the Users controller, params[:id] will be the user id 1, so the effect is the same as the find method User.find(1) we saw in Section 6.1.4. (Technically, params[:id] is the string "1", but find is smart enough to convert this to an integer.)
With the user view and action defined, the URL /users/1 works perfectly, as seen in Figure 7.6. (If you haven’t restarted the Rails server since adding bcrypt, you may have to do so at this time.) Note that the debug information in Figure 7.6 confirms the value of params[:id]:
---
action: show
controller: users
id: '1'
This is why the code
User.find(params[:id])
in Listing 7.5 finds the user with id 1.

We saw in Section 7.1.2 how the information in the debug could help us understand what’s going on in our application. As of Rails 4.2, there’s an even more direct way to get debugging information using the byebug gem (Listing 3.2). To see how it works, we just need to add a line consisting of debugger to our application, as shown in Listing 7.6.
app/controllers/users_controller.rb
class UsersController < ApplicationController
def show
@user = User.find(params[:id])
debugger
end
def new
end
end
Now, when we visit /users/1, the Rails server shows a byebug prompt:
(byebug)
We can treat this like a Rails console, issuing commands to figure out the state of the application:
(byebug) @user.name
"Example User"
(byebug) @user.email
"example@railstutorial.org"
(byebug) params[:id]
"1"
To release the prompt and continue execution of the application, press Ctrl-D, then remove the debugger line from the show action (Listing 7.7).
app/controllers/users_controller.rb
class UsersController < ApplicationController
def show
@user = User.find(params[:id])
end
def new
end
end
Whenever you’re confused about something in a Rails application, it’s a good practice to put debugger close to the code you think might be causing the trouble. Inspecting the state of the system using byebug is a powerful method for tracking down application errors and interactively debugging your application.
Having defined a basic user page in the previous section, we’ll now flesh it out a little with a profile image for each user and the first cut of the user sidebar. We’ll start by adding a “globally recognized avatar”, or Gravatar, to the user profile.6 Gravatar is a free service that allows users to upload images and associate them with email addresses they control. As a result, Gravatars are a convenient way to include user profile images without going through the trouble of managing image upload, cropping, and storage; all we need to do is construct the proper Gravatar image URL using the user’s email address and the corresponding Gravatar image will automatically appear. (We’ll learn how to handle custom image upload in Section 11.4.)
Our plan is to define a gravatar_for helper function to return a Gravatar image for a given user, as shown in Listing 7.8.
app/views/users/show.html.erb
<% provide(:title, @user.name) %>
<h1>
<%= gravatar_for @user %>
<%= @user.name %>
</h1>
By default, methods defined in any helper file are automatically available in any view, but for convenience we’ll put the gravatar_for method in the file for helpers associated with the Users controller. As noted in the Gravatar documentation, Gravatar URLs are based on an MD5 hash of the user’s email address. In Ruby, the MD5 hashing algorithm is implemented using the hexdigest method, which is part of the Digest library:
>> email = "MHARTL@example.COM"
>> Digest::MD5::hexdigest(email.downcase)
=> "1fda4469bcbec3badf5418269ffc5968"
Since email addresses are case-insensitive (Section 6.2.4) but MD5 hashes are not, we’ve used the downcase method to ensure that the argument to hexdigest is all lower-case. (Because of the email downcasing callback in Listing 6.31, this will never make a difference in this tutorial, but it’s a good practice in case the gravatar_for ever gets used on email addresses from other sources.) The resulting gravatar_for helper appears in Listing 7.9.
gravatar_for helper method. app/helpers/users_helper.rb
module UsersHelper
# Returns the Gravatar for the given user.
def gravatar_for(user)
gravatar_id = Digest::MD5::hexdigest(user.email.downcase)
gravatar_url = "https://secure.gravatar.com/avatar/#{gravatar_id}"
image_tag(gravatar_url, alt: user.name, class: "gravatar")
end
end
The code in Listing 7.9 returns an image tag for the Gravatar with a gravatar CSS class and alt text equal to the user’s name (which is especially convenient for sight-impaired users using a screen reader).
The profile page appears as in Figure 7.7, which shows the default Gravatar image, which appears because user@example.com isn’t a real email address. (In fact, as you can see by visiting it, the example.com domain is reserved for examples like this one.)
To get our application to display a custom Gravatar, we’ll use update_attributes (Section 6.1.5) to change the user’s email to something I control:
$ rails console
>> user = User.first
>> user.update_attributes(name: "Example User",
?> email: "example@railstutorial.org",
?> password: "foobar",
?> password_confirmation: "foobar")
=> true
Here we’ve assigned the user the email address example@railstutorial.org, which I’ve associated with the Rails Tutorial logo, as seen in Figure 7.8.
The last element needed to complete the mockup from Figure 7.1 is the initial version of the user sidebar. We’ll implement it using the aside tag, which is used for content (such as sidebars) that complements the rest of the page but can also stand alone. We include row and col-md-4 classes, which are both part of Bootstrap. The code for the modified user show page appears in Listing 7.10.
show view. app/views/users/show.html.erb
<% provide(:title, @user.name) %>
<div class="row">
<aside class="col-md-4">
<section class="user_info">
<h1>
<%= gravatar_for @user %>
<%= @user.name %>
</h1>
</section>
</aside>
</div>
With the HTML elements and CSS classes in place, we can style the profile page (including the sidebar and the Gravatar) with the SCSS shown in Listing 7.11.7 (Note the nesting of the table CSS rules, which works only because of the Sass engine used by the asset pipeline.) The resulting page is shown in Figure 7.9.
app/assets/stylesheets/custom.css.scss
.
.
.
/* sidebar */
aside {
section.user_info {
margin-top: 20px;
}
section {
padding: 10px 0;
margin-top: 20px;
&:first-child {
border: 0;
padding-top: 0;
}
span {
display: block;
margin-bottom: 3px;
line-height: 1;
}
h1 {
font-size: 1.4em;
text-align: left;
letter-spacing: -1px;
margin-bottom: 3px;
margin-top: 0px;
}
}
}
.gravatar {
float: left;
margin-right: 10px;
}
.gravatar_edit {
margin-top: 15px;
}

Now that we have a working (though not yet complete) user profile page, we’re ready to make a signup form for our site. We saw in Figure 5.9 (shown again in Figure 7.10) that the signup page is currently blank: useless for signing up new users. The goal of this section is to start changing this sad state of affairs by producing the signup form mocked up in Figure 7.11.


Since we’re about to add the ability to create new users through the web, let’s remove the user created at the console in Section 6.3.4. The cleanest way to do this is to reset the database with the db:migrate:reset Rake task:
$ bundle exec rake db:migrate:reset
On some systems you might have to restart the web server (using Ctrl-C) for the changes to take effect.
form_forThe heart of the signup page is a form for submitting the relevant signup information (name, email, password, confirmation). We can accomplish this in Rails with the form_for helper method, which takes in an Active Record object and constructs a form using the object’s attributes.
Recalling that the signup page /signup is routed to the new action in the Users controller (Listing 5.34), our first step is to create the User object required as an argument to form_for. The resulting @user variable definition appears in Listing 7.12.
@user variable to the new action. app/controllers/users_controller.rb
class UsersController < ApplicationController
def show
@user = User.find(params[:id])
end
def new
@user = User.new
end
end
The form itself appears as in Listing 7.13. We’ll discuss it in detail in Section 7.2.2, but first let’s style it a little with the SCSS in Listing 7.14. (Note the reuse of the box_sizing mixin from Listing 7.2.) Once these CSS rules have been applied, the signup page appears as in Figure 7.12.
app/views/users/new.html.erb
<% provide(:title, 'Sign up') %>
<h1>Sign up</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for(@user) do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :email %>
<%= f.email_field :email %>
<%= f.label :password %>
<%= f.password_field :password %>
<%= f.label :password_confirmation, "Confirmation" %>
<%= f.password_field :password_confirmation %>
<%= f.submit "Create my account", class: "btn btn-primary" %>
<% end %>
</div>
</div>
app/assets/stylesheets/custom.css.scss
.
.
.
/* forms */
input, textarea, select, .uneditable-input {
border: 1px solid #bbb;
width: 100%;
margin-bottom: 15px;
@include box_sizing;
}
input {
height: auto !important;
}

To understand the form defined in Listing 7.13, it’s helpful to break it into smaller pieces. We’ll first look at the outer structure, which consists of embedded Ruby opening with a call to form_for and closing with end:
<%= form_for(@user) do |f| %>
.
.
.
<% end %>
The presence of the do keyword indicates that form_for takes a block with one variable, which we’ve called f (for “form”).
As is usually the case with Rails helpers, we don’t need to know any details about the implementation, but what we do need to know is what the f object does: when called with a method corresponding to an HTML form element—such as a text field, radio button, or password field—f returns code for that element specifically designed to set an attribute of the @user object. In other words,
<%= f.label :name %>
<%= f.text_field :name %>
creates the HTML needed to make a labeled text field element appropriate for setting the name attribute of a User model.
If you look at the HTML for the generated form by Ctrl-clicking and using the “inspect element” function of your browser, the page’s source should look something like Listing 7.15. Let’s take a moment to discuss its structure.
<form accept-charset="UTF-8" action="/users" class="new_user"
id="new_user" method="post">
<input name="utf8" type="hidden" value="✓" />
<input name="authenticity_token" type="hidden"
value="NNb6+J/j46LcrgYUC60wQ2titMuJQ5lLqyAbnbAUkdo=" />
<label for="user_name">Name</label>
<input id="user_name" name="user[name]" type="text" />
<label for="user_email">Email</label>
<input id="user_email" name="user[email]" type="email" />
<label for="user_password">Password</label>
<input id="user_password" name="user[password]"
type="password" />
<label for="user_password_confirmation">Confirmation</label>
<input id="user_password_confirmation"
name="user[password_confirmation]" type="password" />
<input class="btn btn-primary" name="commit" type="submit"
value="Create my account" />
</form>
We’ll start with the internal structure of the document. Comparing Listing 7.13 with Listing 7.15, we see that the embedded Ruby
<%= f.label :name %>
<%= f.text_field :name %>
produces the HTML
<label for="user_name">Name</label>
<input id="user_name" name="user[name]" type="text" />
while
<%= f.label :email %>
<%= f.email_field :email %>
produces the HTML
<label for="user_email">Email</label>
<input id="user_email" name="user[email]" type="email" />
and
<%= f.label :password %>
<%= f.password_field :password %>
produces the HTML
<label for="user_password">Password</label>
<input id="user_password" name="user[password]" type="password" />
As seen in Figure 7.13, text and email fields (type="text" and type="email") simply display their contents, whereas password fields (type="password") obscure the input for security purposes, as seen in Figure 7.13. (The benefit of using an email field is that some systems treat it differently from a text field; for example, the code type="email" will cause some mobile devices to display a special keyboard optimized for entering email addresses.)

text and password fields.
As we’ll see in Section 7.4, the key to creating a user is the special name attribute in each input:
<input id="user_name" name="user[name]" - - - />
.
.
.
<input id="user_password" name="user[password]" - - - />
These name values allow Rails to construct an initialization hash (via the params variable) for creating users using the values entered by the user, as we’ll see in Section 7.3.
The second important element is the form tag itself. Rails creates the form tag using the @user object: because every Ruby object knows its own class (Section 4.4.1), Rails figures out that @user is of class User; moreover, since @user is a new user, Rails knows to construct a form with the post method, which is the proper verb for creating a new object (Box 3.2):
<form action="/users" class="new_user" id="new_user" method="post">
Here the class and id attributes are largely irrelevant; what’s important is action="/users" and method="post". Together, these constitute instructions to issue an HTTP POST request to the /users URL. We’ll see in the next two sections what effects this has.
(You may also have noticed the code that appears just inside the form tag:
<div style="display:none">
<input name="utf8" type="hidden" value="✓" />
<input name="authenticity_token" type="hidden"
value="NNb6+J/j46LcrgYUC60wQ2titMuJQ5lLqyAbnbAUkdo=" />
</div>
This code, which isn’t displayed in the browser, is used internally by Rails, so it’s not important for us to understand what it does. Briefly, it uses the Unicode character ✓ (a checkmark ✓) to force browsers to submit data using the right character encoding, and then it includes an authenticity token, which Rails uses to thwart an attack called a cross-site request forgery (CSRF).)8
Although we’ve briefly examined the HTML for the form in Figure 7.12 (shown in Listing 7.15), we haven’t yet covered any details, and the form is best understood in the context of signup failure. In this section, we’ll create a signup form that accepts an invalid submission and re-renders the signup page with a list of errors, as mocked up in Figure 7.14.

Recall from Section 7.1.2 that adding resources :users to the routes.rb file (Listing 7.3) automatically ensures that our Rails application responds to the RESTful URLs from Table 7.1. In particular, it ensures that a POST request to /users is handled by the create action. Our strategy for the create action is to use the form submission to make a new user object using User.new, try (and fail) to save that user, and then render the signup page for possible resubmission. Let’s get started by reviewing the code for the signup form:
<form action="/users" class="new_user" id="new_user" method="post">
As noted in Section 7.2.2, this HTML issues a POST request to the /users URL.
Our first step toward a working signup form is adding the code in Listing 7.16. This listing includes a second use of the render method, which we first saw in the context of partials (Section 5.1.3); as you can see, render works in controller actions as well. Note that we’ve taken this opportunity to introduce an if-else branching structure, which allows us to handle the cases of failure and success separately based on the value of @user.save, which (as we saw in Section 6.1.3) is either true or false depending on whether or not the save succeeds.
create action that can handle signup failure. app/controllers/users_controller.rb
class UsersController < ApplicationController
def show
@user = User.find(params[:id])
end
def new
@user = User.new
end
def create
@user = User.new(params[:user]) # Not the final implementation!
if @user.save
# Handle a successful save.
else
render 'new'
end
end
end
Note the comment: this is not the final implementation. But it’s enough to get us started, and we’ll finish the implementation in Section 7.3.2.
The best way to understand how the code in Listing 7.16 works is to submit the form with some invalid signup data. The result appears in Figure 7.15, and the full debug information (with an increased font size) appears in Figure 7.16. (Figure 7.15 also shows the web console, which opens a Rails console in the browser to assist in debugging. It’s useful for examining, e.g., the User model, but in this case we need to inspect params, which is not available in the web console as far as I can tell.)


To get a better picture of how Rails handles the submission, let’s take a closer look at the user part of the parameters hash from the debug information (Figure 7.16):
"user" => { "name" => "Foo Bar",
"email" => "foo@invalid",
"password" => "[FILTERED]",
"password_confirmation" => "[FILTERED]"
}
This hash gets passed to the Users controller as part of params, and we saw starting in Section 7.1.2 that the params hash contains information about each request. In the case of a URL like /users/1, the value of params[:id] is the id of the corresponding user (1 in this example). In the case of posting to the signup form, params instead contains a hash of hashes, a construction we first saw in Section 4.3.3, which introduced the strategically named params variable in a console session. The debug information above shows that submitting the form results in a user hash with attributes corresponding to the submitted values, where the keys come from the name attributes of the input tags seen in Listing 7.13; for example, the value of
<input id="user_email" name="user[email]" type="email" />
with name "user[email]" is precisely the email attribute of the user hash.
Although the hash keys appear as strings in the debug output, we can access them in the Users controller as symbols, so that params[:user] is the hash of user attributes—in fact, exactly the attributes needed as an argument to User.new, as first seen in Section 4.4.5 and appearing in Listing 7.16. This means that the line
@user = User.new(params[:user])
is mostly equivalent to
@user = User.new(name: "Foo Bar", email: "foo@invalid",
password: "foo", password_confirmation: "bar")
In previous versions of Rails, using
@user = User.new(params[:user])
actually worked, but it was insecure by default and required a careful and error-prone procedure to prevent malicious users from potentially modifying the application database. In Rails version later than 4.0, this code raises an error (as seen in Figure 7.15 and Figure 7.16 above), which means it is secure by default.
We mentioned briefly in Section 4.4.5 the idea of mass assignment, which involves initializing a Ruby variable using a hash of values, as in
@user = User.new(params[:user]) # Not the final implementation!
The comment included in Listing 7.16 and reproduced above indicates that this is not the final implementation. The reason is that initializing the entire params hash is extremely dangerous—it arranges to pass to User.new all data submitted by a user. In particular, suppose that, in addition to the current attributes, the User model included an admin attribute used to identify administrative users of the site. (We will implement just such an attribute in Section 9.4.1.) The way to set such an attribute to true is to pass the value admin=’1’ as part of params[:user], a task that is easy to accomplish using a command-line HTTP client such as curl. The result would be that, by passing in the entire params hash to User.new, we would allow any user of the site to gain administrative access by including admin=’1’ in the web request.
Previous versions of Rails used a method called attr_accessible in the model layer to solve this problem, and you may still see that method in legacy Rails applications, but as of Rails 4.0 the preferred technique is to use so-called strong parameters in the controller layer. This allows us to specify which parameters are required and which ones are permitted. In addition, passing in a raw params hash as above will cause an error to be raised, so that Rails applications are now immune to mass assignment vulnerabilities by default.
In the present instance, we want to require the params hash to have a :user attribute, and we want to permit the name, email, password, and password confirmation attributes (but no others). We can accomplish this as follows:
params.require(:user).permit(:name, :email, :password, :password_confirmation)
This code returns a version of the params hash with only the permitted attributes (while raising an error if the :user attribute is missing).
To facilitate the use of these parameters, it’s conventional to introduce an auxiliary method called user_params (which returns an appropriate initialization hash) and use it in place of params[:user]:
@user = User.new(user_params)
Since user_params will only be used internally by the Users controller and need not be exposed to external users via the web, we’ll make it private using Ruby’s private keyword, as shown in Listing 7.17. (We’ll discuss private in more detail in Section 8.4.)
create action. app/controllers/users_controller.rb
class UsersController < ApplicationController
.
.
.
def create
@user = User.new(user_params)
if @user.save
# Handle a successful save.
else
render 'new'
end
end
private
def user_params
params.require(:user).permit(:name, :email, :password,
:password_confirmation)
end
end
By the way, the extra level of indentation on the user_params method is designed to make it visually apparent which methods are defined after private. (Experience shows that this is a wise practice; in classes with a large number of methods, it is easy to define a private method accidentally, which leads to considerable confusion when it isn’t available to call on the corresponding object.)
At this point, the signup form is working, at least in the sense that it no longer produces an error upon submission. On the other hand, as seen in Figure 7.17, it doesn’t display any feedback on invalid submissions (apart from the development-only debug area), which is potentially confusing. It also doesn’t actually create a new user. We’ll fix the first issue in Section 7.3.3 and the second in Section 7.4.

As a final step in handling failed user creation, we’ll add helpful error messages to indicate the problems that prevented successful signup. Conveniently, Rails automatically provides such messages based on the User model validations. For example, consider trying to save a user with an invalid email address and with a password that’s too short:
$ rails console
>> user = User.new(name: "Foo Bar", email: "foo@invalid",
?> password: "dude", password_confirmation: "dude")
>> user.save
=> false
>> user.errors.full_messages
=> ["Email is invalid", "Password is too short (minimum is 6 characters)"]
Here the errors.full_messages object (which we saw briefly before in Section 6.2.2) contains an array of error messages.
As in the console session above, the failed save in Listing 7.16 generates a list of error messages associated with the @user object. To display the messages in the browser, we’ll render an error-messages partial on the user new page while adding the CSS class form-control (which has special meaning to Bootstrap) to each entry field, as shown in Listing 7.18. It’s worth noting that this error-messages partial is only a first attempt; the final version appears in Section 11.3.2.
app/views/users/new.html.erb
<% provide(:title, 'Sign up') %>
<h1>Sign up</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for(@user) do |f| %>
<%= render 'shared/error_messages' %>
<%= f.label :name %>
<%= f.text_field :name, class: 'form-control' %>
<%= f.label :email %>
<%= f.email_field :email, class: 'form-control' %>
<%= f.label :password %>
<%= f.password_field :password, class: 'form-control' %>
<%= f.label :password_confirmation, "Confirmation" %>
<%= f.password_field :password_confirmation, class: 'form-control' %>
<%= f.submit "Create my account", class: "btn btn-primary" %>
<% end %>
</div>
</div>
Notice here that we render a partial called ’shared/error_messages’; this reflects the common Rails convention of using a dedicated shared/ directory for partials expected to be used in views across multiple controllers. (We’ll see this expectation fulfilled in Section 9.1.1.) This means that we have to create a new app/views/shared directory using mkdir (Table 1.1):
$ mkdir app/views/shared
We then need to create the _error_messages.html.erb partial file using our text editor as usual. The contents of the partial appear in Listing 7.19.
app/views/shared/_error_messages.html.erb
<% if @user.errors.any? %>
<div id="error_explanation">
<div class="alert alert-danger">
The form contains <%= pluralize(@user.errors.count, "error") %>.
</div>
<ul>
<% @user.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
This partial introduces several new Rails and Ruby constructs, including two methods for Rails error objects. The first method is count, which simply returns the number of errors:
>> user.errors.count
=> 2
The other new method is any?, which (together with empty?) is one of a pair of complementary methods:
>> user.errors.empty?
=> false
>> user.errors.any?
=> true
We see here that the empty? method, which we first saw in Section 4.2.3 in the context of strings, also works on Rails error objects, returning true for an empty object and false otherwise. The any? method is just the opposite of empty?, returning true if there are any elements present and false otherwise. (By the way, all of these methods—count, empty?, and any?—work on Ruby arrays as well. We’ll put this fact to good use starting in Section 11.2.)
The other new idea is the pluralize text helper. It isn’t available in the console by default, but we can include it explicitly through the ActionView::Helpers::TextHelper module:9
>> include ActionView::Helpers::TextHelper
>> pluralize(1, "error")
=> "1 error"
>> pluralize(5, "error")
=> "5 errors"
We see here that pluralize takes an integer argument and then returns the number with a properly pluralized version of its second argument. Underlying this method is a powerful inflector that knows how to pluralize a large number of words, including many with irregular plurals:
>> pluralize(2, "woman")
=> "2 women"
>> pluralize(3, "erratum")
=> "3 errata"
As a result of its use of pluralize, the code
<%= pluralize(@user.errors.count, "error") %>
returns "0 errors", "1 error", "2 errors", and so on, depending on how many errors there are, thereby avoiding ungrammatical phrases such as "1 errors" (a distressingly common mistake in apps and on the Web).
Note that Listing 7.19 includes the CSS id error_explanation for use in styling the error messages. (Recall from Section 5.1.2 that CSS uses the pound sign # to style ids.) In addition, after an invalid submission Rails automatically wraps the fields with errors in divs with the CSS class field_with_errors. These labels then allow us to style the error messages with the SCSS shown in Listing 7.20, which makes use of Sass’s @extend function to include the functionality of the Bootstrap class has-error.
app/assets/stylesheets/custom.css.scss
.
.
.
/* forms */
.
.
.
#error_explanation {
color: red;
ul {
color: red;
margin: 0 0 30px 0;
}
}
.field_with_errors {
@extend .has-error;
.form-control {
color: $state-danger-text;
}
}
With the code in Listing 7.18 and Listing 7.19 and the SCSS from Listing 7.20, helpful error messages now appear when submitting invalid signup information, as seen in Figure 7.18. Because the messages are generated by the model validations, they will automatically change if you ever change your mind about, say, the format of email addresses, or the minimum length of passwords. (Note: Because both the presence validation and the has_secure_password validation catch the case of empty (nil) passwords, the signup form currently produces duplicate error messages when the user submits empty passwords. We could manipulate the error messages directly to eliminate duplicates, but luckily this issue will be fixed automatically by the addition of allow_nil: true in Section 9.1.4.)

In the days before powerful web frameworks with full testing capabilities, developers had to test forms by hand. For example, to test a signup page manually, we would have to visit the page in a browser and then submit alternately invalid and valid data, verifying in each case that the application’s behavior was correct. Moreover, we would have to remember to repeat the process any time the application changed. This process was painful and error-prone.
Happily, with Rails we can write tests to automate the testing of forms. In this section, we’ll write one such test to verify the correct behavior upon invalid form submission; in Section 7.4.4, we’ll write a corresponding test for valid submission.
To get started, we first generate an integration test file for signing up users, which we’ll call users_signup (adopting the controller convention of a plural resource name):
$ rails generate integration_test users_signup
invoke test_unit
create test/integration/users_signup_test.rb
(We’ll use this same file in Section 7.4.4 to test a valid signup.)
The main purpose of our test is to verify that clicking the signup button results in not creating a new user when the submitted information is invalid. (Writing a test for the error messages is left as an exercise (Section 7.7).) The way to do this is to check the count of users, and under the hood our tests will use the count method available on every Active Record class, including User:
$ rails console
>> User.count
=> 0
Here User.count is 0 because we reset the database at the beginning of Section 7.2. As in Section 5.3.4, we’ll use assert_select to test HTML elements of the relevant pages, taking care to check only elements unlikely to change in the future.
We’ll start by visiting the signup path using get:
get signup_path
In order to test the form submission, we need to issue a POST request to the users_path (Table 7.1), which we can do with the post function:
assert_no_difference 'User.count' do
post users_path, user: { name: "",
email: "user@invalid",
password: "foo",
password_confirmation: "bar" }
end
Here we’ve included the params[:user] hash expected by User.new in the create action (Listing 7.24). By wrapping the post in the assert_no_difference method with the string argument ’User.count’, we arrange for a comparison between User.count before and after the contents of the assert_no_difference block. This is equivalent to recording the user count, posting the data, and verifying that the count is the same:
before_count = User.count
post users_path, ...
after_count = User.count
assert_equal before_count, after_count
Although the two are equivalent, using assert_no_difference is cleaner and is more idiomatically correct Ruby.
It’s worth noting that the get and post steps above are technically unrelated, and it’s actually not necessary to get the signup path before posting to the users path. I prefer to include both steps, though, both for conceptual clarity and to double-check that the signup form renders without error.
Putting the above ideas together leads to the test in Listing 7.21. We’ve also included a call to assert_template to check that a failed submission re-renders the new action. Adding lines to check for the appearance of error messages is left as an exercise (Section 7.7).
test/integration/users_signup_test.rb
require 'test_helper'
class UsersSignupTest < ActionDispatch::IntegrationTest
test "invalid signup information" do
get signup_path
assert_no_difference 'User.count' do
post users_path, user: { name: "",
email: "user@invalid",
password: "foo",
password_confirmation: "bar" }
end
assert_template 'users/new'
end
end
Because we wrote the application code before the integration test, the test suite should be green:
$ bundle exec rake test
Having handled invalid form submissions, now it’s time to complete the signup form by actually saving a new user (if valid) to the database. First, we try to save the user; if the save succeeds, the user’s information gets written to the database automatically, and we then redirect the browser to show the user’s profile (together with a friendly greeting), as mocked up in Figure 7.19. If it fails, we simply fall back on the behavior developed in Section 7.3.

To complete a working signup form, we need to fill in the commented-out section in Listing 7.17 with the appropriate behavior. Currently, the form fails on valid submission. As indicated in Figure 7.20, this is because the default behavior for a Rails action is to render the corresponding view, and there isn’t a view template corresponding to the create action.

Rather than render a page on successful user creation, we’ll instead redirect to a different page. We’ll follow the common convention of redirecting to the newly created user’s profile, although the root path would also work. The application code, which introduces the redirect_to method, appears in Listing 7.23.
create action with a save and a redirect. app/controllers/users_controller.rb
class UsersController < ApplicationController
.
.
.
def create
@user = User.new(user_params)
if @user.save
redirect_to @user
else
render 'new'
end
end
private
def user_params
params.require(:user).permit(:name, :email, :password,
:password_confirmation)
end
end
Note that we’ve written
redirect_to @user
where we could have used the equivalent
redirect_to user_url(@user)
This is because Rails automatically infers from redirect_to @user that we want to redirect to user_url(@user).
With the code in Listing 7.23, our signup form is actually working, but before submitting a valid registration in a browser we’re going to add a bit of polish common in web applications: a message that appears on the subsequent page (in this case, welcoming our new user to the application) and then disappears upon visiting a second page or on page reload.
The Rails way to display a temporary message is to use a special method called the flash, which we can treat like a hash. Rails adopts the convention of a :success key for a message indicating a successful result (Listing 7.24).
app/controllers/users_controller.rb
class UsersController < ApplicationController
.
.
.
def create
@user = User.new(user_params)
if @user.save
flash[:success] = "Welcome to the Sample App!"
redirect_to @user
else
render 'new'
end
end
private
def user_params
params.require(:user).permit(:name, :email, :password,
:password_confirmation)
end
end
By assigning a message to the flash, we are now in a position to display the message on the first page after the redirect. Our method is to iterate through the flash and insert all relevant messages into the site layout. You may recall the console example in Section 4.3.3, where we saw how to iterate through a hash using the strategically named flash variable:
$ rails console
>> flash = { success: "It worked!", danger: "It failed." }
=> {:success=>"It worked!", danger: "It failed."}
>> flash.each do |key, value|
?> puts "#{key}"
?> puts "#{value}"
>> end
success
It worked!
danger
It failed.
By following this pattern, we can arrange to display the contents of the flash site-wide using code like this:
<% flash.each do |message_type, message| %>
<div class="alert alert-<%= message_type %>"><%= message %></div>
<% end %>
(This code is a particularly ugly combination of HTML and ERb; making it prettier is left as an exercise (Section 7.7).) Here the embedded Ruby
alert-<%= message_type %>
makes a CSS class corresponding to the type of message, so that for a :success message the class is
alert-success
(The key :success is a symbol, but embedded Ruby automatically converts it to the string "success" before inserting it into the template.) Using a different class for each key allows us to apply different styles to different kinds of messages. For example, in Section 8.1.4 we’ll use flash[:danger] to indicate a failed login attempt.10 (In fact, we’ve already used alert-danger once, to style the error message div in Listing 7.19.) Bootstrap CSS supports styling for four such flash classes (success, info, warning, and danger), and we’ll find occasion to use all of them in the course of developing the sample application.
Because the message is also inserted into the template, the full HTML result for
flash[:success] = "Welcome to the Sample App!"
appears as follows:
<div class="alert alert-success">Welcome to the Sample App!</div>
Putting the embedded Ruby discussed above into the site layout leads to the code in Listing 7.25.
flash variable to the site layout. app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
.
.
.
<body>
<%= render 'layouts/header' %>
<div class="container">
<% flash.each do |message_type, message| %>
<div class="alert alert-<%= message_type %>"><%= message %></div>
<% end %>
<%= yield %>
<%= render 'layouts/footer' %>
<%= debug(params) if Rails.env.development? %>
</div>
.
.
.
</body>
</html>
We can see the result of all this work by signing up our first user under the name “Rails Tutorial” and email address “example@railstutorial.org” (Figure 7.21). The resulting page (Figure 7.22) shows a friendly message upon successful signup, including nice green styling for the success class, which comes included with the Bootstrap CSS framework from Section 5.1.2. (If instead you get an error message indicating that the email address has already been taken, be sure to run the db:migrate:reset Rake task as indicated in Section 7.2 and restart the development webserver.) Then, upon reloading the user show page, the flash message disappears as promised (Figure 7.23).



We can now check our database just to double-check that the new user was actually created:
$ rails console
>> User.find_by(email: "example@railstutorial.org")
=> #<User id: 1, name: "Rails Tutorial", email: "example@railstutorial.org",
created_at: "2014-08-29 19:53:17", updated_at: "2014-08-29 19:53:17",
password_digest: "$2a$10$zthScEx9x6EkuLa4NolGye6O0Zgrkp1B6LQ12pTHlNB...">
Before moving on, we’ll write a test for valid submission to verify our application’s behavior and catch regressions. As with the test for invalid submission in Section 7.3.4, our main purpose is to verify the contents of the database. In this case, we want to submit valid information and then confirm that a user was created. In analogy with Listing 7.21, which used
assert_no_difference 'User.count' do
post users_path, ...
end
here we’ll use the corresponding assert_difference method:
assert_difference 'User.count', 1 do
post_via_redirect users_path, ...
end
As with assert_no_difference, the first argument is the string ’User.count’, which arranges for a comparison between User.count before and after the contents of the assert_difference block. The second (optional) argument specifies the size of the difference (in this case, 1).
Incorporating assert_difference into the file from Listing 7.21 yields the test shown in Listing 7.26. Note that we’ve used the post_via_redirect variant to post to the users path. This simply arranges to follow the redirect after submission, resulting in a rendering of the ’users/show’ template. (It’s probably a good idea to write a test for the flash as well, which is left as an exercise (Section 7.7).)
test/integration/users_signup_test.rb
require 'test_helper'
class UsersSignupTest < ActionDispatch::IntegrationTest
.
.
.
test "valid signup information" do
get signup_path
assert_difference 'User.count', 1 do
post_via_redirect users_path, user: { name: "Example User",
email: "user@example.com",
password: "password",
password_confirmation: "password" }
end
assert_template 'users/show'
end
end
Note that Listing 7.26 also verifies that the user show template renders following successful signup. For this test to work, it’s necessary for the Users routes (Listing 7.3), the Users show action (Listing 7.5), and the show.html.erb view (Listing 7.8) to work correctly. As a result, the one line
assert_template 'users/show'
is a sensitive test for almost everything related to a user’s profile page. This sort of end-to-end coverage of important application features illustrates one reason why integration tests are so useful.
Now that we have a working signup page, it’s time to deploy our application and get it working in production. Although we started deploying our application in Chapter 3, this is the first time it will actually do something, so we’ll take this opportunity to make the deployment professional-grade. In particular, we’ll add an important feature to the production application to make signup secure, and we’ll replace the default web server with one suitable for real-world use.
As preparation for the deployment, you should merge your changes into the master branch at this point:
$ git add -A
$ git commit -m "Finish user signup"
$ git checkout master
$ git merge sign-up
When submitting the signup form developed in this chapter, the name, email address, and password get sent over the network, and hence are vulnerable to intercept. This is a potentially serious security flaw in our application, and the way to fix it is to use Secure Sockets Layer (SSL)11 to encrypt all relevant information before it leaves the local browser. Although we could use SSL on just the signup page, it’s actually easier to implement it site-wide, which has the additional benefits of securing user login (Chapter 8) and making our application immune to a critical session hijacking vulnerability discussed in Section 8.4.
Enabling SSL is as easy as uncommenting a single line in production.rb, the configuration file for production applications. As shown in Listing 7.27, all we need to do is set the config variable to force the use of SSL in production.
config/environments/production.rb
Rails.application.configure do
.
.
.
# Force all access to the app over SSL, use Strict-Transport-Security,
# and use secure cookies.
config.force_ssl = true
.
.
.
end
At this stage, we need to set up SSL on the remote server. Setting up a production site to use SSL involves purchasing and configuring an SSL certificate for your domain. That’s a lot of work, though, and luckily we won’t need it here: for an application running on a Heroku domain (such as the sample application), we can piggyback on Heroku’s SSL certificate. As a result, when we deploy the application in Section 7.5.2, SSL will automatically be enabled. (If you want to run SSL on a custom domain, such as www.example.com, refer to Heroku’s page on SSL.)
Having added SSL, we now need to configure our application to use a webserver suitable for production applications. By default, Heroku uses a pure-Ruby webserver called WEBrick, which is easy to set up and run but isn’t good at handling significant traffic. As a result, WEBrick isn’t suitable for production use, so we’ll replace WEBrick with Puma, an HTTP server that is capable of handling a large number of incoming requests.
To add the new webserver, we simply follow the Heroku Puma documentation. The first step is to include the puma gem in our Gemfile, as shown in Listing 7.28. Because we don’t need the Puma gem locally, Listing 7.28 puts it in the :production group.
Gemfile.
source 'https://rubygems.org'
.
.
.
group :production do
gem 'pg', '0.17.1'
gem 'rails_12factor', '0.0.2'
gem 'puma', '3.1.0'
end
Because we configured Bundler not to install production gems (Section 3.1), Listing 7.28 won’t add any gems to the development environment, but we still need to run Bundler to update Gemfile.lock:
$ bundle install
The next step is to create a file called config/puma.rb and fill it with the contents of Listing 7.29. The code in Listing 7.29 comes straight from the Heroku documentation,12 and there is no need to understand it.
config/puma.rb
workers Integer(ENV['WEB_CONCURRENCY'] || 2)
threads_count = Integer(ENV['MAX_THREADS'] || 5)
threads threads_count, threads_count
preload_app!
rackup DefaultRackup
port ENV['PORT'] || 3000
environment ENV['RACK_ENV'] || 'development'
on_worker_boot do
# Worker specific setup for Rails 4.1+
# See: https://devcenter.heroku.com/articles/
# deploying-rails-applications-with-the-puma-web-server#on-worker-boot
ActiveRecord::Base.establish_connection
end
Finally, we need to make a so-called Procfile to tell Heroku to run a Puma process in production, as shown in Listing 7.30. The Procfile should be created in your application’s root directory (i.e., in the same location as the Gemfile).
Procfile for Puma. ./Procfile
web: bundle exec puma -C config/puma.rb
With the production webserver configuration completed, we’re ready to commit and deploy:13
$ bundle exec rake test
$ git add -A
$ git commit -m "Use SSL and the Puma webserver in production"
$ git push
$ git push heroku
$ heroku run rake db:migrate
The signup form is now live, and the result of a successful signup is shown in Figure 7.24. Note the presence of https:// and a lock icon in the address bar of Figure 7.24, which indicate that SSL is working.

When deploying to Heroku, you may get a warning message like this one:
###### WARNING:
You have not declared a Ruby version in your Gemfile.
To set your Ruby version add this line to your Gemfile:
ruby '2.1.5'
Experience shows that, at the level of this tutorial, the costs associated with including such an explicit Ruby version number outweigh the (negligible) benefits, so you should ignore this warning for now. The main issue is that keeping your sample app and system in sync with the latest Ruby version can be a huge inconvenience,14 and yet it almost never makes a difference which exact Ruby version number you use. Nevertheless, you should bear in mind that, should you ever end up running a mission-critical app on Heroku, specifying an exact Ruby version in the Gemfile is recommended to ensure maximum compatibility between development and production environments.
Being able to sign up users is a major milestone for our application. Although the sample app has yet to accomplish anything useful, we have laid an essential foundation for all future development. In Chapter 8, we will complete our authentication machinery by allowing users to log in and out of the application. In Chapter 9, we will allow all users to update their account information, and we will allow site administrators to delete users, thereby completing the full suite of Users resource REST actions from Table 7.1.
debug method.
development, test, and production.
form_for helper is used to make forms for interacting with Active Record objects.
flash as a standard way to display temporary messages.
For a suggestion on how to avoid conflicts between exercises and the main tutorial, see the note on exercise topic branches in Section 3.6.
gravatar_for helper defined in Section 7.1.4 to take an optional size parameter, allowing code like gravatar_for user, size: 50 in the view. (We’ll put this improved helper to use in Section 9.3.1.)
FILL_IN with the appropriate code. (Even testing for the right key, much less the text, is likely to be brittle, so I prefer only to test that the flash isn’t empty.)
content_tag helper, also works.
gravatar_for helper. app/helpers/users_helper.rb
module UsersHelper
# Returns the Gravatar for the given user.
def gravatar_for(user, options = { size: 80 })
gravatar_id = Digest::MD5::hexdigest(user.email.downcase)
size = options[:size]
gravatar_url = "https://secure.gravatar.com/avatar/#{gravatar_id}?s=#{size}"
image_tag(gravatar_url, alt: user.name, class: "gravatar")
end
end
test/integration/users_signup_test.rb
require 'test_helper'
class UsersSignupTest < ActionDispatch::IntegrationTest
test "invalid signup information" do
get signup_path
assert_no_difference 'User.count' do
post users_path, user: { name: "",
email: "user@invalid",
password: "foo",
password_confirmation: "bar" }
end
assert_template 'users/new'
assert_select 'div#<CSS id for error explanation>'
assert_select 'div.<CSS class for field with error>'
end
.
.
.
end
test/integration/users_signup_test.rb
require 'test_helper'
.
.
.
test "valid signup information" do
get signup_path
assert_difference 'User.count', 1 do
post_via_redirect users_path, user: { name: "Example User",
email: "user@example.com",
password: "password",
password_confirmation: "password" }
end
assert_template 'users/show'
assert_not flash.FILL_IN
end
end
flash ERb in the site layout using content_tag. app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
.
.
.
<% flash.each do |message_type, message| %>
<%= content_tag(:div, message, class: "alert alert-#{message_type}") %>
<% end %>
.
.
.
</html>
debug information is shown as YAML (a recursive acronym standing for “YAML Ain’t Markup Language”), which is a friendly data format designed to be both machine- and human-readable. ↑edit action of the Users controller, but since the edit action doesn’t exist yet actually hitting that URL will return an error. ↑.gravatar_edit class, which we’ll put to work in Chapter 9. ↑pluralize in the Rails API. ↑flash.now, but we’ll defer that subtlety until we need it. ↑heroku run rake db:migrate as a final step just to be safe. ↑