It was around 2 months ago that I started to dig deep into Ruby on Rails, when I needed a plugin to handle authentication. That time, Ruby on Rails 3 was newly published, when so many gems still hadn't updated their compatibility to Rails update, including Authlogic . Authlogic was the first authentication gem that I used as an authentication plugin, but I couldn't use it anymore since I had to use Rails 3 in my project. That moment brought me to Devise . Devise was already compatible to Rails 3 and so my research began. The research concluded:
Devise was very easy to use. The modules were developed in a very good structure.
Devise provided 11 modules that I could use to authenticate my application.
Devise allowed me to customize some of its modules to meet my application requirement.
These are the reasons that strongly influenced me to develop an application with Devise. It saved my time from developing new authentication modules from scratch. Now, we have reached Ruby on Rails 4; Devise was quickly updated so that developers could use it within the new Rails environment.
Database Authenticatable: This module will encrypt and store a password in the database to validate the authenticity of a user while signing in. The authentication can be done both through POST requests or HTTP Basic Authentication . This is the basic module to perform authentication with Devise.
Omniauthable: Attach OmniAuth support to Devise. By turning this module on, your application will allow the user to sign in with external accounts such as Facebook and Twitter. We will talk about this in more detail in Chapter 3, Privileges.
Confirmable : Attach this module to enable the confirmation mechanism. So, Devise will send an e-mail with a confirmation instruction and verify whether an account is already confirmed during the sign-in process.
Recoverable: There are times when users forget their passwords and need to recover it. This module is the answer for that need. Devise will allow the user to reset passwords and it will send the user the instructions via e-mail.
Rememberable : It's very often, when you visit a login page of a website, you will see a sentence, Remember Me, with a checkbox beside it. It will be used to remember the logged-in user by storing a cookie. In Devise, you can implement this method by attaching this module.
Trackable : For certain websites, the sign-in tracker is very useful. The data can be very helpful to retrieve some information. If you choose Devise to handle your authorization mechanisms, you will be able to do it. Devise provides this module to track sign-in processes, so a user can collect information regarding sign-in count, timestamps, and the IP address.
Lockable : If you are willing to add more security to your application, this module could be very handy. Lockable will manage the maximum count of failed sign-in attempts. When it reaches the maximum number, Devise will lock the account. The user can unlock it via e-mail or after a specified time period.
These 11 modules are the essence of Devise. With these modules, you can do anything related to application authorization, which is very useful in modern applications.
Rails 4 (4.0.0)
Devise 3 (3.0.3)
SQLite 3 (1.3.8)
$ rails new learning-devise
The first thing that should be done is you need to add the Devise gem to your
To make sure that everything is installed properly, you can execute the following command inside your Rails application folder:
$ bundle install
The command will install the Devise gem, and now you have to install the configuration files for Devise. You can install it all at once by executing the following command:
$ rails generate devise:install
The result of the command is shown in the following screenshot:
The basic URL configuration that applies to every environment setting. The code shown in the screenshot should be added to the environment settings, so that Devise will acknowledge the application URL which is used in its autogenerated e-mail. Especially for production, the host value should be filled with your actual application domain.
The route setting that you need to add to your
config/routes.rbfile. By defining your root URL, Devise will use it for its redirection. For example, Devise will redirect the user to the root URL after they sign out from the application.
Devise helpers that can be used to generate errors or warning messages when there's something wrong with the code. This is very useful and you can write it in your views file.
Configuration that you need to add when deploying to Heroku. I'm not going to discuss about it in this book.
How to generate copies of Devise views, so that you can customize it later. We will see how it works in Chapter 2, Authenticating Your Application with Devise.
The next step is generating a Devise model. Let's name our Devise model as user. For your information, this model name can be replaced with any name you wish. This name also determines the Devise helper's name. We will see how we use it later in this chapter. To generate the Devise model, you can execute the following command:
$ rails generate devise user
The result of this command can be seen in the following screenshot:
The first kind is used as a migration file. This file is shown as
db/migrate/20130915133401_devise_create_users.rb. Like the other migration files, it is used to generate tables in our database.
A model file that is shown as
A test file that is shown as
test/models/user_test.rb. This file is used to perform testing. We will discuss this topic in Chapter 5, Testing Devise.
A fixture file that is shown as
test/fixtures/users.yml. This file is used to perform testing. We will discuss this topic in Chapter 5, Testing Devise.
The command also modifies the model file to attach the default modules and the route file (
routes.rb). Devise modifies the route so the application recognizes some routes generated by Devise. This is the code which is added by Devise to the route file:
Now, let's open a user model file (
user.rb) and you're going to see this code:
class User < ActiveRecord::Base # Include default devise modules. Others available # are: # :token_authenticatable, :encryptable, # :confirmable, :lockable, :timeoutable and # :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable end
From the code, we will know that Devise will attach some default modules such as Database Authenticable, Registerable, Recoverable, Rememberable, Trackable, and Validatable. As I wrote earlier in this chapter, I suppose you already knew what the modules are for.
At this point, you have prepared all the basic settings that a Rails application needs to implement Devise. So, the next step is creating the table on your database by migrating the migration file. If you don't make any change to the Devise migration file, it means Devise will only generate columns for its default modules. But, if you make some changes like commenting on other modules such as
t.tocken_authenticatble, you will have extra columns in your user's table that will handle some specific Devise modules. So, it depends on your requirement whether you are going to use the modules or not.
We have prepared our migration file, now let's create the table. I presume that you already have the database and have prepared the database configuration at
config/database.yml. If so, all you need to do is execute this command:
$ rake db:migrate
Now, you have prepared everything to make Devise run smoothly on your Rails application. But, there's one more thing that I want to show you. It's about how to wrap controllers with your authorization and see it in action.
In this section, we are going to talk about how to wrap your controllers with Devise authorization and use some Devise helper in your views. First, I want to generate a single controller by executing this command:
$ rails generate controller home index
This command will generate the controller (
home_controller.rb) with an action named
index. It also generates a view file located at
views/home/index.html.erb. Let's start by opening the controller file and add a code (
:authenticate_user!) between class definition and first action definition. Why
:authenticate_user!? As I stated before, we have our Devise model named as user and this code is one of the Devise helpers that I meant. So, in the future, when you have a Devise model with a different name, you can change the user part in the code with your actual model name. According to our example, the controller code will be like the following:
class HomeController < ApplicationController before_filter :authenticate_user! def index end end
By adding the highlighted code, your Rails application will run the controller filter, which is executed before executing all the actions defined in the controller. You can also modify the filter so that it will be executed only for all actions using
:except code. By adding this code, you will be able to define which actions should be authorized and which should not. For example, it will be like the following code:
class HomeController < ApplicationController before_filter :authenticate_user!, :only => [:index, :new] def index end def new end def edit end end
The code shows that the actions
new are authorized, so users need to sign in before getting into the action page.
Now, let's start our Rails server by executing the command
$ rails server. See it in action by visiting
http://localhost:3000. The application will automatically redirect you to the sign-in page, like this:
Now, you have run your first application with Devise. With current modules, you can only perform sign-in, sign-up, reset password, remember me action, and sign-in tracker. We will play with other modules in the next chapters, but before that, I want to show some Devise's helpers, which are very helpful in view files. Those helpers are as follows:
current_user: This helper will be very useful to get the data model of a currently logged-in user. With this method, you are able to retrieve data stored in the database anytime you want it. For example, if I want to get the e-mail of the current logged-in user, I can retrieve it by calling the method
user_signed_in?: This helper returns a Boolean data type, which determines whether a user is logged-in or not. For example, with this method you can hide and show sign-out link in your view. Here is the sample code for this case (
<h1>Home#index</h1> <p>Find me in app/views/home/index.html.erb</p> <br> <% if user_signed_in? %> <%= link_to 'Sign Out', destroy_user_session_path, method: :delete %> <% end %>
user_session: This is a session variable that can set anything you want in a hash format. Actually, this helper contains the subset of the Ruby on Rails session data. So, the purpose of this helper is to simplify the use of Rails sessions. Despite using the
sessionvariable for every Devise model that you have, you can utilize the session helper, so the session grouping for your model will be clear. For example, I want to save a string inside the session helper, I can do it by writing this code:
user_session[:hello] = "world"
These helpers are the ones that I mentioned before. The actual name is based on your Devise model name. So, when you create or use another model name, you can use all these helpers by replacing the user keyword in the helpers name with the one that you have.