Fork me on GitHub
Hoopla! - now with extra whiz-bang home

Today the underground team of rorBB (an as-yet-unannounced Rails BB) saw that the application was almost completely RESTful - except in it’s login/logout actions on the users controller. It was Ben who pointed out that it was the single thing destroying our otherwise pretty URLs and we decided to do something about it.

I admit that I’ve been slow to get on the REST bandwagon. Why is that you proverbially ask? To tell the truth it’s largely because I CAN’T FIND A DEFINITION ANYWHERE. I went to Wikipedia, oracle of all wisdom, only to be told how it differs from RPC. I have a long, rich history of coding in PHP. That means I dont know shit about real programming and I had to then go and lookup RPC.

So forgive me if I act like this is the biggest, most amazing discovery ever. I’m just really happy that I discovered it before everybody had moved on to the Next Big Thing©.

So, regarding our controllers: the code we had was fairly generic. On the users controller there were the standard new, create, update, edit, etc. actions but then we had two others:

UsersController with RESTless actions:

    def login
      if request.post?
        user = User.authenticate(params[:name], params[:password])
        unless user.nil?
          session[:user_id] = user.id
          redirect_to users_url
        else
          flash[:error] = 'Username or password is incorrect'
        end
      end
    end

    def logout
      reset_session
      redirect_to :action => 'login'
    end

In other apps I’ve written this was pretty standard. Sometimes they’d be in a ‘users’ controller, sometimes in an ‘auth’ controller that contained just these two actions.

It wasn’t until I saw a lot of high-quality REST programming that I started to see there was a better way of doing things than just throwing actions in controllers that might fit.

So we talked about the possibility of overhauling our code to allow for a sessions controller that followed the basic verbs of REST. I figured it would take a while but might eventually pay off.

Boy was I surprised to find that even an idiot like me could put it together quickly. Here’s the final code from the sessions controller:

    class SessionsController < ApplicationController

      def create
        user = User.authenticate(params[:name], params[:password])
        unless user.nil?
          session[:user_id] = user.id
          redirect_to users_url
        else
          flash[:error] = 'Username or password is incorrect'
          redirect_to new_session_url
        end
      end

      def destroy
        reset_session
        flash[:notice] = "You are now logged out"
        redirect_to new_session_url
      end

    end

If you ignore a couple of slight improvements in the second piece of code you might notice that I ONLY RENAMED THINGS. Can you believe it? Our whole app fit back into REST with some very minor changes.

So, what’s the benefit of the sessions controller? Well, besides getting a free API (though you may never need to build a session over API) the tests got simpler, the routes.rb file got WAY, WAY simpler (back to just one line of code for all our controllers), and our team got just a little bit happier.

And who doesn’t like to be happy?

Update: By request, here’s the original and the modified routes.rb file:

    ActionController::Routing::Routes.draw do |map|

      map.connect '', :controller => 'forums'

      map.resources *%w[forums topics posts users]

      map.resources :users, :collection => { :login => :get }
      map.resources :users, :collection => { :login => :post }
      map.resources :users, :collection => { :logout => :post }

      map.connect ':controller/:action/:id'

    end
    ActionController::Routing::Routes.draw do |map|

      map.home '', :controller => 'forums'

      map.resources *%w[forums topics posts users sessions]

      map.connect ':controller/:action/:id'

    end

You might notice that even in the first file the routes are using the new map.resources command (normally used for this REST stuff).

blog comments powered by Disqus