Posted October 24, 2012 by Spyros in Ruby on Rails

Customize Your Routes And Controllers For Devise in Rails 3


Devise is probably the leading Rails 3 authentication gem nowadays. It is pretty powerful and allows you to do many things over your authentication, such as use omniauth, send activation emails and much more. Setting it is pretty easy, but customizing it to work for your controllers can be quite painful. In a recent project, i had to do quite a bit of customizing in Devise, in order to get it working.

How to Redirect User to Your Controller After Logging or Registering ?

That is one of the most important first changes that you would most probably need to do. The Devise Wiki offers some insight on how to do that, but unluckily, the documentation is aimed towards more advanced Rails users and you may have some difficulty getting things done, if you just started with Rails. Therefore, i will be describing the process.

Devise is looking for a certain named route, in order to know where to redirect a user after logging or registering. But, what is a named route ? Take a look at this line below :

get '/user' => 'town#index', :as => 'user_root'

I will not extensively discuss Rails 3 routing in this post(certainly in a future one though), but there are some things that you need to know now. This line actually comes from routes.rb, the file that holds our routing rules for a particular project. If you just start with Rails, i would highly recommend that you take a close look to routing and actually write your routes.rb file from scratch.

In this line, we specify what happens after a user makes a GET request to /user. That is, if our website is railsclub.com, he gets the page railsclub.com/user. The => arrow specifies that when a user does that, he will be directed to the town controller and the index action is going to be executed( => controller#action). Therefore, we now know what is supposed to happen. In the end, the :as => ‘user_root’, specifies that this particular route now has a name. It’s called user_root.

But why would we name a route ? Well, that is kind of a standard powerful practice in Rails. It’s a great way to better clarify your code. Think of the case where we have a link :

<%= link_to "Home", :controller => 'town', :action => 'index' %>

This is fine, but what about this version :

<%= link_to "Home", user_root_path %>

So much better, don’t you think ? Imagine that “town#index” also received a parameter like a @user_id, in order to specify the user whose details are going to be presented. Then, it would become :

<%= link_to "Home", user_root_path(@user_id) %>

Pretty powerful and simplistic coding. This is definitively a technique that you need to follow. But let’s go back to our subject now. We know that Devise is looking for that user_root named route and we take advantage of that. We override the route and set it to our “controller#action”. Make sure that you also have the line in your routes.rb :

devise_for :users

:users can be any model that devise connects to. This line is important because it sets all the needed routes for devise to work. You can go to your project and write :

rake routes

in order to take a look at how your routes look now. Hope that saves you some trouble with making Devise work for you.