ruby-on-railsrubyruby-on-rails-3authlogic

Authlogic root url based on authenticated state


I'd like to be able to set the root url in routes.rb based on the logged in/out state of Authlogic. Here is an example of what I need to do:

root :to => 'users#index', :constraints => lambda { |request| # ??? }  
root :to => 'welcome#index'  
get '/' => 'users#index', :as => 'user_root'

This would enable logged in users to go to users#index and logged out users to go to welcome#index without doing a redirect. I do know how to set a before_filter and redirect accordingly, but I'd rather not do that.

I know this is possible with Devise but I need to solve this for Authlogic. Similar question here without an answer.


Solution

  • You can create a custom route constraint pretty easily. Any object that responds to matches? can be handed to the :constraints route option. To check for Authlogic authentication, you would need to pull your Authlogic methods from your ApplicationController and put them somewhere else. I recommend using a concern for these anyways.

    # app/concerns/authlogic_methods.rb
    module AuthlogicHelpers
      extend ActiveSupport::Concern
    
      module InstanceMethods
        private # All methods are private
    
        def current_user_session
          return @current_user_session if defined?(@current_user_session)
          @current_user_session = UserSession.find
        end
    
        def current_user
          return @current_user if defined?(@current_user)
          @current_user = current_user_session && current_user_session.user
        end
      end
    end
    
    # app/controllers/application_controller.rb
    class ApplicationController < ActionController::Base
      include AuthlogicHelpers
    end
    
    # config/initializers/route_constraints.rb
    module RouteConstraints
      class LoggedIn
        include AuthlogicHelpers
        def matches?(request)
          current_user
        end
      end
    end
    
    # config/routes.rb
    constraints RouteConstraints::LoggedIn.new do
      root :to => 'dashboard#show'
    end
    

    Note that we're instantiating a new RouteConstraints::LoggedIn object. This is because the Authlogic methods current_user and current_user_session are defined as instance methods and create instance variables — if they aren't separated for each request, you won't be sure a user is actually logged in or another one was logged in before.

    You might run into problems if Authlogic tries to access params directly. In this case, you will probably need to override the UserSession.new method to accept the request object as an argument and call request.params to get the params.