-
Notifications
You must be signed in to change notification settings - Fork 0
tutorial rails devise rspec cucumber
Last updated 16 May 2012
Ruby on Rails tutorial showing how to create a Rails 3.2 application using Devise with RSpec and Cucumber.
- Devise gives you ready-made authentication and user management.
- RSpec is a popular alternative to the Test::Unit testing framework.
- Cucumber is used for Behaviour Driven Development.
Here’s what you can do:
- learn as-you-go by following the steps in this tutorial to build a starter app
- clone the example code from the GitHub repo for a ready-to-use starter app
- generate a customized starter app with an application template
Generating the application gives you many options, such as using Haml for views, additional Devise modules, and various HTML5/CSS front-end frameworks such as Twitter Bootstrap.
This is one in a series of Rails example apps and tutorials from the RailsApps Project. See a list of similar Rails examples, tutorials, and starter apps.
This example application uses ActiveRecord and a SQLite database. You can use the Mongoid ORM with the MongoDB datastore instead, for faster development without schemas or migrations. The rails3-mongoid-devise example app and tutorial shows how to set up Devise and Mongoid with RSpec and Cucumber.
Follow the project on Twitter: rails_apps. Tweet some praise if you like what you’ve found.
This tutorial documents each step that you must follow to create this application. Every step is documented concisely, so a complete beginner can create this application without any additional knowledge. However, no explanation is offered for any of the steps, so if you are a beginner, you’re advised to look for an introduction to Rails elsewhere. See resources for getting started with Rails.
If you follow this tutorial closely, you’ll have a working application that closely matches the example app in this GitHub repository. The example app in the rails3-devise-rspec-cucumber repository is your reference implementation. If you find problems with the app you build from this tutorial, download the example app (in Git speak, clone it) and use a file compare tool to identify differences that may be causing errors. On a Mac, good file compare tools are FileMerge, DiffMerge, Kaleidoscope, or Ian Baird’s Changes.
If you clone and install the example app and find problems or wish to suggest improvements, please create a GitHub issue.
To improve this tutorial, please edit this wiki page or leave comments below.
Follow this tutorial.
To create the application, you can cut and paste the code from the tutorial into your own files. It’s a bit tedious and error-prone but you’ll have a good opportunity to examine the code closely.
Use the ready-made application template to generate the code.
You can use an application template to generate a new Rails app with code that closely matches the tutorial. You’ll find an application template for this tutorial in the Rails Application Templates repository.
You’ll be able to give it your own project name when you generate the app. Generating the application (described below) gives you many options, such as using Haml for views, additional Devise modules, and various HTML5/CSS front-end frameworks such as Twitter Bootstrap.
Use the command:
$ rails new rails3-devise-rspec-cucumber -m https://raw.github.com/RailsApps/rails3-application-templates/master/rails3-devise-rspec-cucumber-template.rb -T
Use the -T
flag to skip Test::Unit files.
The $
character indicates a shell prompt; don’t include it when you run the command.
This creates a new Rails app named rails3-devise-rspec-cucumber
on your computer. You can use a different name if you wish.
The application generator template will ask you for your preferences.
To produce an application exactly like the tutorial, make the following selections:
- Would you like to use Haml instead of ERB? no
- Would you like to use RSpec instead of TestUnit? yes
- Would you like to use factory_girl for test fixtures with RSpec? yes
- Would you like to use machinist for test fixtures with RSpec? no
- Would you like to use Cucumber for your BDD? yes
- Would you like to use Guard to automate your workflow? no
- Would you like the app to use a Gmail account to send email? yes
- Would you like to use Devise for authentication?
- No
- Devise with default modules #2
- Devise with Confirmable module
- Devise with Confirmable and Invitable modules
- Would you like to manage authorization with CanCan & Rolify? no
- Which front-end framework would you like for HTML5 and CSS3?
- None #1
- Zurb Foundation
- Twitter Bootstrap (less)
- Twitter Bootstrap (sass)
- Skeleton
- Normalize CSS for consistent styling
- Which form gem would you like?
- None #1
- simple form
- simple form (bootstrap)
- Would you like to use rails-footnotes during development? no
- Would you like to set a robots.txt file to ban spiders? yes
- Would you like to add ‘will_paginate’ for pagination? no
- Add ‘therubyracer’ JavaScript runtime (for Linux users without node.js)? no
You can choose other selections if you don’t care about matching the example application exactly.
You can choose the Devise with Confirmable module option if you want new users to confirm their email address before gaining access to your site. If you don’t wish to require email confirmation, choose the option Devise with default modules.
Use the rails_apps_composer gem to create a reusuable application template.
This is optimal if you are creating a “starter app” based on this example app but wish to customize the code for your own preferences.
Each step in this tutorial has a corresponding application template recipe from the Rails Apps Composer recipes repository. You can create your own application template using the template recipes. To do so, clone the Rails Apps Composer project, customize recipes as needed, and follow the instructions to create a reusable application template file.
Before beginning this tutorial, you need to install
- The Ruby language (version 1.9.3 or newer)
- Rails 3.2
Check that appropriate versions of Ruby and Rails are installed in your development environment:
$ ruby -v
$ rails -v
Be sure to read Installing Rails for detailed instructions and advice.
Beginning here, we show how to create the application from scratch.
Open a terminal, navigate to a folder where you have rights to create files, and type:
$ rails new rails3-devise-rspec-cucumber -T
Use the -T
flag to skip Test::Unit files (since you are using RSpec).
You may give the app a different name if you are building it for your own use. For this tutorial, we’ll assume the name is “rails3-devise-rspec-cucumber.”
This will create a Rails application that uses a SQLite database for data storage.
After you create the application, switch to its folder to continue work directly in that application:
$ cd rails3-devise-rspec-cucumber
If you’re open sourcing the app on GitHub, please edit the README file to add a description of the app and your contact info. Changing the README is important if you’re using a clone of the example app. I’ve been mistaken (and contacted) as the author of apps that are copied from my example.
If you are creating an application template, this step uses the git recipe from the rails_apps_composer repository
If you’re creating an app for deployment into production, you’ll want to set up a source control repository at this point. If you are building a throw-away app for your own education, you may skip this step.
$ git init .
$ git add .
$ git commit -m 'Initial commit'
See detailed instructions for Using Git with Rails.
The application uses the following gems:
It’s a good idea to create a new gemset using rvm, the Ruby Version Manager, as described in the article Installing Rails.
See Example Gemfiles for Rails 3.2.
Open your Gemfile and replace the contents with the following:
Gemfile
source 'https://rubygems.org' gem 'rails', '3.2.3' gem 'sqlite3' group :assets do gem 'sass-rails', '~> 3.2.3' gem 'coffee-rails', '~> 3.2.1' gem 'uglifier', '>= 1.0.3' end gem 'jquery-rails' gem "rspec-rails", ">= 2.10.1", :group => [:development, :test] gem "factory_girl_rails", ">= 3.3.0", :group => [:development, :test] gem "email_spec", ">= 1.2.1", :group => :test gem "cucumber-rails", ">= 1.3.0", :group => :test, :require => false gem "capybara", ">= 1.1.2", :group => :test gem "database_cleaner", ">= 0.7.2", :group => :test gem "launchy", ">= 2.1.0", :group => :test gem "devise", ">= 2.1.0"
Check for the current version of Rails and replace gem 'rails', '3.2.3'
accordingly.
Note: The RailsApps examples are generated with application templates created by the Rails Apps Composer Gem. For that reason, groups such as :development
or :test
are specified inline. You can reformat the Gemfiles to organize groups in an eye-pleasing block style. The functionality is the same.
Install the required gems on your computer:
$ bundle install
You can check which gems are installed on your computer with:
$ gem list --local
Keep in mind that you have installed these gems locally. When you deploy the app to another server, the same gems (and versions) must be available.
If you are creating an application template, this step uses the haml recipe from the rails_apps_composer repository
In this tutorial, we’ll use the default “ERB” Rails template engine. Optionally, you can use another template engine, such as Haml. See instructions for adding Haml to Rails.
If you are creating an application template, this step uses the rspec recipe from the rails_apps_composer repository
This tutorial shows how to set up RSpec and provides example specs for use with Devise. To learn more about using RSpec, refer to The RSpec Book.
Use the gem rspec-rails to set up the app for RSpec.
You should have the following gems in your Gemfile:
gem 'rspec-rails', :group => [:development, :test] group :test do gem 'database_cleaner' gem 'factory_girl_rails' gem 'email_spec' end
The gem rspec-rails
needs to be in the :development
group (as well as the :test
group) to expose generators and rake tasks during development.
Install the required gems on your computer:
$ bundle install
Use the rspec-rails generator to set up files needed for RSpec:
$ rails generate rspec:install
The rspec-rails generator creates the files:
- .rspec
- spec/spec_helper.rb
In you did not include the -T option when you ran rails new, you can remove the test folder (it is not needed for RSpec):
$ rm -rf test/
The factory_girl gem is used to create default model objects for tests. For example, if a controller action requires finding a User object before displaying a “show” page, Factory Girl will create a user just for a test of the controller. You’ll need gem 'factory_girl_rails', :group => :test
in your Gemfile.
You’ll need a spec/factories/users.rb file to contain the factory definitions for any default objects used for testing. You can create one like this:
spec/factories/users.rb
FactoryGirl.define do factory :user do name 'Test User' email 'example@example.com' password 'please' password_confirmation 'please' # required if the Devise Confirmable module is used # confirmed_at Time.now end end
If you’ve chosen to create the application with the Devise Confirmable module, remove the commenting to enable confirmed_at Time.now
.
Using Devise, your controllers will often include before_filter :authenticate_user!
to limit access to signed-in users. Your tests will fail unless a default user is created and logs in before each test runs. Devise provides test helpers to make it simple to create and log in a default user.
Create a file spec/support/devise.rb:
spec/support/devise.rb
RSpec.configure do |config| config.include Devise::TestHelpers, :type => :controller end
Now you can write controller specs that set up a signed-in user before tests are run.
The email_spec gem provides a collection of RSpec matchers for testing email.
Modify the file spec/spec_helper.rb to enable the email_spec library:
# This file is copied to spec/ when you run 'rails generate rspec:install' ENV["RAILS_ENV"] ||= 'test' require File.expand_path("../../config/environment", __FILE__) require 'rspec/rails' require 'email_spec' require 'rspec/autorun' . . . RSpec.configure do |config| config.include(EmailSpec::Helpers) config.include(EmailSpec::Matchers) # ## Mock Framework . . . end
Don’t copy the dots. Leave the file intact and just add the email_spec lines.
By default, using a Rails generator to create a controller will create placeholder unit tests for helpers and views.
We’re using Cucumber scenarios (integration tests) so unit tests of helpers and views are redundant. Tell the Rails generator to skip unit tests for helpers and views.
Modify the file config/application.rb to include:
# don't generate RSpec tests for views and helpers config.generators do |g| g.view_specs false g.helper_specs false end
Run rake -T
to check that rake tasks for RSpec are available.
Prepare the database for testing by running the commands:
$ bundle exec rake db:migrate $ bundle exec rake db:test:prepare
This will create a db/schema.rb file so rake spec
can run successfully.
You should be able to run rake spec
to run all specs. If you haven’t written any specs, you’ll see the message “No examples matching … could be found”.
You can copy the files from the example spec directory to use our ready-made specs.
$ cd spec $ mkdir controllers $ cd controllers $ curl -o home_controller_spec.rb https://raw.github.com/RailsApps/rails3-devise-rspec-cucumber/master/spec/controllers/home_controller_spec.rb $ curl -o users_controller_spec.rb https://raw.github.com/RailsApps/rails3-devise-rspec-cucumber/master/spec/controllers/users_controller_spec.rb $ cd ../ $ mkdir models $ cd models $ curl -o user_spec.rb https://raw.github.com/RailsApps/rails3-devise-rspec-cucumber/master/spec/models/user_spec.rb $ cd ../../
Now you can run rake spec
to see failing tests.
You’ll have to complete the tutorial before the specs will run successfully.
If you are creating an application template, this step uses the cucumber recipe from the rails_apps_composer repository
It’s not necessary to add Cucumber (the example will run without it). However, it’s a recommended practice to describe application functionality as “user stories” documented as Cucumber scenarios. It’s a good way to plan development and, using Cucumber, you’ll have specifications for automated acceptance testing. To learn more about using Cucumber, refer to The Cucumber Book.
This tutorial shows how to set up Cucumber with Devise.
Use the gem cucumber-rails to set up the app for Cucumber.
You should have the following gems in your Gemfile file:
group :test do gem 'cucumber-rails' gem 'capybara' gem 'database_cleaner' gem "email_spec" end
Install the required gems on your computer (if you haven’t already done so):
$ bundle install
Use the cucumber-rails generator to set up files needed for Cucumber:
$ rails generate cucumber:install --capybara --rspec
The -–capybara
option specifies Capybara instead of the default Webrat for acceptance testing. The -–rspec
option enables RSpec matchers for your step definitions.
The cucumber-rails generator creates the directories:
- features/step_definitions
- features/support
The cucumber-rails generator creates the files:
- config/cucumber.yml
- features/support/env.rb
- lib/tasks/cucumber.rake
- script/cucumber
To reset your application database to a pristine state during testing, Cucumber makes use of Database Cleaner. The file features/support/env.rb is already set up to use Database Cleaner:
begin DatabaseCleaner.strategy = :transaction rescue NameError raise "You need to add database_cleaner to your Gemfile (in the :test group) if you wish to use it." end
The email_spec gem provides a collection of Cucumber steps for testing email.
Add a file support/email_spec.rb to enable the email_spec library:
require 'email_spec/cucumber'
Create a set of Cucumber step definitions for testing email:
$ rails generate email_spec:steps
This creates a file features/step_definitions/email_steps.rb.
You can run a single Cucumber feature with a command such as:
$ bundle exec cucumber features/visitors/request_invitation.feature --require features
To save some typing, you can eliminate the need for --require features
by changing the config/cucumber.yml file:
std_opts = "-r features/support/ -r features/step_definitions --format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} --strict --tags ~@wip"
Run rake -T
to check that rake tasks for Cucumber are available.
You should be able to run rake cucumber
(or more simply, cucumber
) to run all Cucumber scenarios and steps. If you haven’t written any Cucumber scenarios and steps, you’ll see the message “0 scenarios, 0 steps”.
You can copy the files from the example features directory to use our ready-made Cucumber feature files.
$ cd features $ cd support $ curl -o paths.rb https://raw.github.com/RailsApps/rails3-devise-rspec-cucumber/master/features/support/paths.rb $ cd ../ $ cd step_definitions $ curl -o user_steps.rb https://raw.github.com/RailsApps/rails3-devise-rspec-cucumber/master/features/step_definitions/user_steps.rb $ cd ../ $ mkdir users $ cd users $ curl -o sign_in.feature https://raw.github.com/RailsApps/rails3-devise-rspec-cucumber/master/features/users/sign_in.feature $ curl -o sign_out.feature https://raw.github.com/RailsApps/rails3-devise-rspec-cucumber/master/features/users/sign_out.feature $ curl -o sign_up.feature https://raw.github.com/RailsApps/rails3-devise-rspec-cucumber/master/features/users/sign_up.feature $ curl -o user_edit.feature https://raw.github.com/RailsApps/rails3-devise-rspec-cucumber/master/features/users/user_edit.feature $ curl -o user_show.feature https://raw.github.com/RailsApps/rails3-devise-rspec-cucumber/master/features/users/user_show.feature $ cd ../../
If you’ve chosen to create the application with the Devise Confirmable module, you should change one step in the features/step_definitions/user_steps.rb file:
Then /^I should see a successful sign up message$/ do page.should have_content "Welcome! You have signed up successfully." end
should be changed so all Cucumber scenarios pass when the Devise Confirmable module is used:
Then /^I should see a successful sign up message$/ do page.should have_content "A message with a confirmation link has been sent to your email address." end
You can run rake cucumber
to see your failing Cucumber integraton tests.
You’ll have to complete the tutorial before all Cucumber scenarios will run successfully.
To learn more about using Cucumber, refer to The Cucumber Book or the free introduction to Cucumber, The Secret Ninja Cucumber Scrolls.
There are two approaches to writing Cucumber scenarios. The newest (and recommended) approach uses Capybara to write the code (“steps”) that turn Cucumber scenarios into executable specifications. Older versions of Cucumber provided a web_steps.rb
file that implemented common features. See the The Training Wheels Came Off by Aslak Hellesøy to understand why the web_steps.rb
approach is no longer recommended.
You can check that your app runs properly by entering the command
$ rails server
To see your application in action, open a browser window and navigate to http://localhost:3000/. You should see the Rails default information page.
Stop the server with Control-C.
If you are creating an application template, this step uses the action_mailer recipe from the rails_apps_composer repository
You must configure the app for your email account if you want your application to send email messages, for example, if you’ve generated the application with the option to install the Devise :confirmable
module.
Remove the following from the config/environments/development.rb file:
# Don't care if the mailer can't send config.action_mailer.raise_delivery_errors = false
Add the following to the config/environments/development.rb file:
# ActionMailer Config config.action_mailer.default_url_options = { :host => 'localhost:3000' } config.action_mailer.delivery_method = :smtp # change to false to prevent email from being sent during development config.action_mailer.perform_deliveries = true config.action_mailer.raise_delivery_errors = true config.action_mailer.default :charset => "utf-8"
Add the following to the config/environments/production.rb file:
config.action_mailer.default_url_options = { :host => 'example.com' } # ActionMailer Config # Setup for production - deliveries, no errors raised config.action_mailer.delivery_method = :smtp config.action_mailer.perform_deliveries = true config.action_mailer.raise_delivery_errors = false config.action_mailer.default :charset => "utf-8"
Add the following to the config/environments/test.rb file:
# ActionMailer Config config.action_mailer.default_url_options = { :host => 'example.com' }
This will set the example application to deliver email in both development and production. It will raise delivery errors in development but not production.
In development, config.action_mailer.default_url_options
is set for a host at localhost:3000
which will enable links in Devise confirmation email messages to work properly during development.
For testing, config.action_mailer.default_url_options
is set for a host at example.com
. Any value allows tests to run.
For production, you’ll need to change the config.action_mailer.default_url_options
host option from example.com
to your own domain.
If you want to use a Gmail account to send email, you’ll need to modify the files config/environments/development.rb and config/environments/production.rb:
config.action_mailer.smtp_settings = { address: "smtp.gmail.com", port: 587, domain: "example.com", authentication: "plain", enable_starttls_auto: true, user_name: ENV["GMAIL_USERNAME"], password: ENV["GMAIL_PASSWORD"] }
You can replace ENV["GMAIL_USERNAME"]
and ENV["GMAIL_PASSWORD"]
with your Gmail username and password. However, committing the file to a public GitHub repository will expose your secret password.
If you’re familiar with setting Unix environment variables, it’s advisable to leave config.action_mailer.smtp_settings
unchanged and set your environment variables in the file that is read when starting an interactive shell (the ~/.bashrc file for the bash shell). This will keep the password out of your repository.
Are you using a bash shell? Use echo $SHELL
to find out. For a bash shell, edit the ~/.bashrc file and add:
export GMAIL_USERNAME="myname@gmail.com" export GMAIL_PASSWORD="secret*"
Open a new shell or restart your terminal application to continue.
This app uses Devise for user management and authentication.
If you are creating an application template, this step uses the devise recipe from the rails_apps_composer repository
You should have the following gem in your Gemfile file:
gem 'devise'
If you haven’t already, run:
$ bundle install
Run the generator to install Devise:
$ rails generate devise:install
which installs a configuration file:
config/initializers/devise.rb
and a localization file:
config/locales/devise.en.yml
Complete your email configuration by modifying
config/initializers/devise.rb
and setting the config.mailer_sender
option for the return email address for messages that Devise sends from the application.
Devise provides all the code needed for a complete user management and authentication system.
Use Devise to generate models and routes for a User.
$ rails generate devise User
Devise will create a database migration and a User model.
Devise will try to create a spec file for the User model. If you’ve already downloaded the example app spec files, don’t let the Devise generator overwrite the spec/models/user_spec.rb file (enter “n” to prevent overwriting).
Devise will try to create factories for testing the User model. You’ve already created a spec/factories/users.rb file, do don’t let the Devise generator overwrite the spec/factories/users.rb file (enter “n” to prevent overwriting).
Devise will modify the config/routes.rb file to add:
devise_for :users
which provides a complete set of routes for user signup and login. If you run rake routes
you can see the routes that this line of code creates.
By default, Devise uses an http DELETE request for sign out requests (destroy_user_session_path
). Rails uses Javascript to implement http DELETE requests. Prior to Devise 1.4.1 (27 June 2011), Devise used an http GET request for sign out requests. Jose Valim explained the change: “GET requests should not change the state of the server. When sign out is a GET request, CSRF can be used to sign you out automatically and things that preload links can eventually sign you out by mistake as well.”
However, Cucumber wants to test GET requests not DELETE requests. If you intend to use Cucumber with Devise, you must change the Devise default from DELETE to GET in /config/initializers/devise.rb for the Rails test environment. You may see a suggestion elsewhere to tweak the routes.rb file or change the log_out link to make the fix. It isn’t necessary if you change the /config/initializers/devise.rb file.
# The default HTTP method used to sign out a resource. Default is :delete. config.sign_out_via = Rails.env.test? ? :get : :delete
Since you only use Cucumber during testing, switching the default is only needed for testing.
If you’re not going to use Cucumber, leave Devise’s default (DELETE) in place.
We don’t want passwords written to our log file.
Modify the file config/application.rb to include:
config.filter_parameters += [:password, :password_confirmation]
Note that filter_parameters is an array.
If you are creating an application template, this step uses the add_user recipe from the rails_apps_composer repository
By default, Devise uses an email address to identify users. We’ll add a “name” attribute as well. Your application may not require a user to provide a name. But showing you how to add a name will help you see what you need to do if you decide to make changes to the default Devise user model.
Devise created a migration file to establish the schema for the SQLite database with a migration file named something like db/migrate/xxxxxxx_devise_create_users.rb. We won’t modify the migration file. Instead we’ll add an additional migration that adds the “name” field to the User record.
rails generate migration AddNameToUsers name:string
Run the migration and prepare the test database to pick up the “name” field:
$ bundle exec rake db:migrate $ bundle exec rake db:test:prepare
If you wish, you can modify the user model to validate the presence and uniqueness of the “name” attribute. Modify the file app/models/user.rb and add:
validates_presence_of :name validates_uniqueness_of :name, :email, :case_sensitive => false
This will allow users to be created (or edited) with a name attribute. When a user is created, a name and email address must be present and must be unique (not used before). Note that Devise (by default) will check that the email address and password are not blank and that the email address is unique.
You’ll also want to prevent malicious hackers from creating fake web forms that would allow changing of passwords through the mass-assignment operations of update_attributes(attrs) and new(attrs). Devise already added this to the models/user.rb file:
attr_accessible :email, :password, :password_confirmation, :remember_me
but you’ll need to add the “name” attribute:
attr_accessible :name, :email, :password, :password_confirmation, :remember_me
If you’ve chosen to create the application with the Devise Confirmable module, also add :confirmed_at
:
attr_accessible :name, :email, :password, :password_confirmation, :remember_me, :confirmed_at
Devise provides a controller and views for registering users. It is called the “registerable” module. The controller and views are hidden in the Devise gem so we don’t need to create anything. However, because we want our users to provide a name when registering, we will create custom views for creating and editing a user. Our custom views will override the Devise gem defaults.
First, to copy all the default Devise views to your application, run
rails generate devise:views
This will generate a set of views in the directory app/views/devise/.
Next, modify the views to create and edit users.
Add the following code to each file:
app/views/devise/registrations/edit.html.erb
<p><%= f.label :name %><br /> <%= f.text_field :name %></p>
app/views/devise/registrations/new.html.erb
<p><%= f.label :name %><br /> <%= f.text_field :name %></p>
We do not need to add a controller with methods to create a new user or edit or delete a user. We use the existing “registerable” module from Devise which provides a controller with methods to create, edit or delete a user.
Note that Devise’s default behaviour allows any logged-in user to edit or delete his or her own record (but no one else’s). When you access the edit page you are editing just your info, and not info of other users.
If you are using Haml, Devise does not generate views for Haml (it did before Devise 1.2; see Devise issue 878). See How To Create Haml and Slim Views from the Devise wiki.
If you are using Haml, you can generate the ERB files using rails generate devise:views
and then convert them using the online tool Html2Haml. You’ll need to remove the .erb files and replace them with app/views/devise/registrations/edit.html.haml and app/views/devise/registrations/new.html.haml.
If you are creating an application template, this step uses the home_page recipe from the rails_apps_composer repository
Delete the default home page from your application:
$ rm public/index.html
Create the first page of the application. Use the Rails generate command to create a “home” controller and a “views/home/index” page. Specify --no-controller-specs
to avoid overwriting the RSpec files you’ve already downloaded.
$ rails generate controller home index --no-controller-specs
If you’re using the default template engine, you’ll find an erb file with placeholder content:
app/views/home/index.html.erb
Next, set a route to your home page. Edit the file config/routes.rb and replace:
get "home/index"
with
authenticated :user do root :to => 'home#index' end root :to => "home#index"
If you examine this code, you’ll see that authenticated users (those who have an account and are logged in) will see the home/index page as the application root (or home) page. And all other users (those who don’t have an account or who are not logged in) will see the same home page. The redundancy serves a didactic purpose: If you decide you want users to see a different page when they log in, you now know exactly where to change it.
By default, Devise will redirect to the root_path after successful sign in or sign out. It is easy to change the root_path as shown in the config/routes.rb file. Alternatively, you can override the Devise methods after_sign_in_path_for
and after_sign_out_path_for
as described in the Devise wiki article How To Redirect to a Specific Page.
You can check that your app runs properly by entering the command
$ rails server
To see your application in action, open a browser window and navigate to http://localhost:3000/. You should see your new home page.
Stop the server with Control-C.
If you are creating an application template, this step uses the home_page_users recipe from the rails_apps_composer repository
Modify the file app/controllers/home_controller.rb and add:
def index @users = User.all end
Modify the file app/views/home/index.html.erb and add:
<h3>Home</h3> <% @users.each do |user| %> <p>User: <%= user.name %> </p> <% end %>
This code is not appropriate for deployment in a real application. You likely will not want to display a list of users on the home page. However, it is convenient for our example.
If you are creating an application template, this step uses the seed_database recipe from the rails_apps_composer repository
You’ll want to set up a default user so you can test the app. Modify the file db/seeds.rb by adding:
puts 'SETTING UP DEFAULT USER LOGIN' user = User.create! :name => 'First User', :email => 'user@example.com', :password => 'please', :password_confirmation => 'please' puts 'New user created: ' << user.name user2 = User.create! :name => 'Second User', :email => 'user2@example.com', :password => 'please', :password_confirmation => 'please' puts 'New user created: ' << user2.name
If you’ve chosen to create the application with the Devise Confirmable module, add the field confirmed_at
:
puts 'SETTING UP DEFAULT USER LOGIN' user = User.create! :name => 'First User', :email => 'user@example.com', :password => 'please', :password_confirmation => 'please', :confirmed_at => DateTime.now user2 = User.create! :name => 'Second User', :email => 'user2@example.com', :password => 'please', :password_confirmation => 'please', :confirmed_at => DateTime.now puts 'New user created: ' << user.name
You can change the values for name, email, and password as you wish.
Add the default user to the database by running the command:
$ bundle exec rake db:seed
If you need to, you can run $ bundle exec rake db:reset
to drop and then recreate the database using your seeds.rb file.
If the task fails with “Validation failed: Name can’t be blank” you should check that the file models/user.rb allows the “name” attribute to be mass updated:
attr_accessible :name, :email, :password, :password_confirmation, :remember_me
At this point, you may want to know if the default user has been saved to the database.
You can check that your app runs properly by entering the command
$ rails server
To see your application in action, open a browser window and navigate to http://localhost:3000/. You should see your new home page with a list of all the users.
Stop the server with Control-C.
You’ll want to see how Devise manages authentication.
If you are creating an application template, this step uses the users_page recipe from the rails_apps_composer repository
Use the Rails generate command to create a “users” controller and a “views/user/show” page. Specify --no-controller-specs
to avoid overwriting the RSpec files you’ve already downloaded.
$ rails generate controller users index show --no-controller-specs
Note that “users” is plural when you create the controller.
Modify the file app/controllers/users_controller.rb like this:
class UsersController < ApplicationController before_filter :authenticate_user! def index @users = User.all end def show @user = User.find(params[:id]) end end
The file config/routes.rb has been modified to include:
get "users/index" get "users/show"
Remove that and change the routes to:
authenticated :user do root :to => 'home#index' end root :to => "home#index" devise_for :users resources :users, :only => [:show, :index]
Important note: The devise_for :users
route must be placed above resources :users, :only => [:show, :index]
.
Modify the file app/views/users/show.html.erb and add:
<p>User: <%= @user.name %></p> <p>Email: <%= @user.email if @user.email %></p>
Modify the file app/views/users/index.html.erb and add:
<ul class="users"> <% @users.each do |user| %> <li> <%= link_to user.name, user %> signed up <%= user.created_at.to_date %> </li> <% end %> </ul>
You’ve already modified the file app/controllers/home_controller.rb to include this:
def index @users = User.all end
Now modify the file app/views/home/index.html.erb to look like this:
<h3>Home</h3> <% @users.each do |user| %> <p>User: <%=link_to user.name, user %></p> <% end %>
Rails will use the layout defined in the file app/views/layouts/application.html.erb as a default for rendering any page. If you are using Haml, the file will be app/views/layouts/application.html.haml.
You’ll want to add navigation links, include flash messages for errors and notifications, and apply CSS styling. Set up your application layout by modifying the default as described in the instructions for the Rails default application layout.
You can use Twitter Bootstrap or another CSS front-end framework to provide styling. If you’ve generated the app from an application template, the script will offer you Twitter Bootstrap and other choices.
Several unneeded files are generated in the process of creating a new Rails application.
Additionally, you may want to prevent search engines from indexing your website if you’ve deployed it publicly while still in development.
See instructions for cleaning up unneeded files in Rails and banning spiders.
The application is complete. Run your unit and integration tests to see if the application is implemented as intended.
Run rake spec
to see the unit tests. You should see no tests failing.
Run rake cucumber
to see your Cucumber integration tests. You should see all scenarios passing.
You can check that your app runs properly by entering the command
$ rails server
To see your application in action, open a browser window and navigate to http://localhost:3000/. You should see the default user listed on the home page. When you click on the user’s name, you should be required to log in before seeing the user’s detail page.
Stop the server with Control-C.
Heroku provides low cost, easily configured Rails application hosting. For your convenience, see Tutorial: Rails on Heroku.
This concludes the tutorial for creating a Ruby on Rails web application that requires Rails and uses Devise for user management and authentication with RSpec and Cucumber.
Daniel Kehoe implemented the application and wrote the tutorial.
Was this useful to you? Follow rails_apps on Twitter and tweet some praise. I’d love to know you were helped out by the tutorial.
Any issues? Please create an Issue on GitHub.