Tuesday, September 13, 2011

Using Devise for authentication in rails 3

I recently started a new Rails 3 project and was going to use devise for authentication. While very powerful, the documentation was a touch confusing for me and all the other blog posts kept confusing me. What follows are my steps to get up and running with a minimum of effort and thinking.
Step 0, put devise into your Gemfile and run
bundle install
Next, Generate the devise install scripts
$ rails generate devise:install
Devise will spit out:
create  config/initializers/devise.rb
create  config/locales/devise.en.yml


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 it 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:

<p class="notice">
<%= notice %></p>
<p class="alert">
<%= alert %></p>

Gotcha number 1 is that you need TWO entires in routes if you want to enable auto sign up. In addition to what's described above, you'll also need the following line in your routes.rb if you want to enable this:
  devise_for :users
Next, generate the active record files for your User account (I used User, why use anything else?).
$ rails g active_record:devise User
Which spits out the following:
create  db/migrate/20110831002655_devise_create_users.rb
create  app/models/user.rb
invoke  test_unit
create    test/unit/user_test.rb
create    test/fixtures/users.yml
insert  app/models/user.rb

After that, migrate your databse
$ rake db:migrate
==  DeviseCreateUsers: migrating ==============================================
-- create_table(:users)
-> 0.0112s
-- add_index(:users, :email, {:unique=>true})
-> 0.0007s
-- add_index(:users, :reset_password_token, {:unique=>true})
-> 0.0006s
==  DeviseCreateUsers: migrated (0.0128s) =====================================
Generate a controller for your home page (optional if you've got another controller).
$ rails g controller home
Which spits out this:
create  app/controllers/home_controller.rb
invoke  erb
create    app/views/home
invoke  test_unit
create    test/functional/home_controller_test.rb
invoke  helper
create    app/helpers/home_helper.rb
invoke    test_unit
create      test/unit/helpers/home_helper_test.rb
remove app/public/index.html < this is important!
rm app/public/index.html
edit app/controllers/home_controller.rb and make it do something: NOTE: ;we've added the devise before_filter to require login/signup, this is what tells devise that the controller should be secured.
class HomeController < ApplicationController
  before_filter :authenticate_user!
  def index
    render :text => "Welcome #{current_user.email}!"
Next generate the devise views. I don't think this is strictly necessary, but I'm assuming you'll want to customize these after you get going.

$ rails g devise:views
Output should look like this:
      invoke  Devise::Generators::SharedViewsGenerator
      create    app/views/devise/mailer
      create    app/views/devise/mailer/confirmation_instructions.html.erb
      create    app/views/devise/mailer/reset_password_instructions.html.erb
      create    app/views/devise/mailer/unlock_instructions.html.erb
      create    app/views/devise/shared
      create    app/views/devise/shared/_links.erb
      invoke  form_for
      create    app/views/devise/confirmations
      create    app/views/devise/confirmations/new.html.erb
      create    app/views/devise/passwords
      create    app/views/devise/passwords/edit.html.erb
      create    app/views/devise/passwords/new.html.erb
      create    app/views/devise/registrations
      create    app/views/devise/registrations/edit.html.erb
      create    app/views/devise/registrations/new.html.erb
      create    app/views/devise/sessions
      create    app/views/devise/sessions/new.html.erb
      create    app/views/devise/unlocks
      create    app/views/devise/unlocks/new.html.erb
Run your app and you will have auto-signup and authentication enabled. For more infomation about how to further customize your config see the devise web site.


bravo said...

There is something wrong with formatting.

Mike Mainguy said...

Wow! I changed the template and didn't recheck everything... Thanks for the catch, I'll have to look into this.

Tina said...

This is gorgeous!