Using Devise for Authentication in Rails
April 11, 2010 by dave@kiwiluv.com · 6 Comments
In our first application, we used restful authentication for user authentication. For our next one, I evaluated AuthLogic, which is well respected and works well. There’s a new one out there that I’m trying out that I like very much as well called Devise. In contrast to AuthLogic, Devise is full stack and doesn’t operate only on the model. It actually comes with some nice generators to make thing easy to get up quickly. Be really careful to pick the right version if you’re using Rails 3!
Here’s how to build Devise authentication into your app. Note that I initially did this on rails 2.3.5, but decided to revert to early adoption and installed the Rails 3 beta. I do have to say that this works MUCH better in Rails 3 than Rails 2, but the end result is just as good.
First, just install the Devise gem. Rails 3 introduces the Gemfile which looks like it’s going to make handling gems and dependencies a breeze compared to manifests and the old way of doing things. I thought I’d give it a try. Add the following line to your Gemfile:
gem 'devise', '1.1.rc1'
That will tell Rails that it needs v1.1RC1 of the Devise gem. Next run
bundle_install
to parse the Gemfile file and make sure all the various dependencies are met. This type of thing has been the bane of many Rails developer’s existence and this looks like a giant step forward!
But I digress. Now we should have the Devise gem installed and ready to go. Devise has a script which puts everything in place for using Devise in your app. Run the script to set everything up:
rails generate devise_install
You’ll be prompted with the following manual steps to follow to complete installation:
===============================================================================
Some setup you must do manually if you haven't yet:
1. Setup default url options for your specific environment. Here is an
example of development environment:
config.action_mailer.default_url_options = { :host => 'localhost:3000' }
This is a required Rails configuration. In production is must be the
actual host of your application
2. Ensure you have defined root_url to *something* in your config/routes.rb.
For example:
root :to => "home#index"
3. Ensure you have flash messages in app/views/layouts/application.html.erb.
For example:
<%= notice %>
<%= alert %>
===============================================================================
The next step is to create a model with hooks into devise for your users. You can create multiple models (User, Admin, etc.) in order to customize behavior for each one. In this example, I’m just going to create a User model using
rails generate devise User
This creates the necessary models and migration files. Now is the time for some decisions. I’m taking all default modules that Devise offers, however if you do not wish to have all of the modules applied you will need to comment them out in your migration rake file to avoid creating those tables in your database. Once you’re done tweaking, just do
rake db:migrate
To create the database tables, routes, etc. This creates a boatload of routes in your application for user sign in, signout, forgotten password retrieval, etc.
That’s pretty much it except for beautification. Devise comes with it’s own views, which you can customize, but are a great starting point to focus on functionality first. You can simply go to the /users/sign_up URL and create a new user. Do a rake routes to find out everything that Devise just added to your application. It’s a very complete set of functionality.
For a fantastic tutorial on Devise, check out these two RailsCasts by Ryan Bates:
RailsCast #209 – Introducing Devise
RailsCast #210 – Customizing Devise
And naturally the github site linked to at the beginning of this post.
Hey, good info!
FYI your Railscasts links are backwards (meaning #209 links to #210 and vice versa)
Oops…thanks for pointing that out…I corrected it!
Thanks for this. Minor correction: you want bundle install, not bundle_install.
How can I sign out or logout?
the link `http://localhost:3000/users/sign_out` give an error:
Routing Error
No route matches [GET] “/users/sign_out”
Shallen, you’re absolutely right. Sorry for the typo. Sayuj, I’m not sure why you’re having the problem, but it might be that there’s a missing route, so have a look at the routs file.
So people, this is, for some reason, a very popular post. I’ll write a mini-book for kiwitechpress.com on authentication for Rails, including Devise. Also, this post is getting a bit old, so please check these out.
http://railscasts.com/episodes/270-authentication-in-rails-3-1
http://railscasts.com/episodes/250-authentication-from-scratch
The second link is very good. Apparently my boy Ryan Bates noticed that a lot of Rails developers were leaning heavily on Devise and other such magic solutions. While Devise is awesome, understanding how something works at a fundamental level is invaluable so check out that RailsCast.
Finally, our friend Tony Amoyal put a much more complete post on Devise and CanCan (Also by Ryan Bates – Hallowed be his name) which is well worth a look.
http://www.tonyamoyal.com/2010/07/28/rails-authentication-with-devise-and-cancan-customizing-devise-controllers/
I’ll get the minibook out with the re-launch of kiwitechpress.com.
@Sayuj
The routing error is due to the fact that the link is for a delete method whereas you are using a get method on the route. Try running rake routes to see which url uses what method.