Alex Rivera | Logout

How do I handle authentication with Devise when using multiple models in Rails 3.2 App

Asked 2012-04-21T20:12:36.643
12

I'm working on a Rails 3.2 app where I use Devise for authentication. I decided to try single table inheritance for managing user roles, but I quickly ran into a problem. I currently have three User models, User < ActiveRecord, Admin < User and Collaborator < User. Admin and Collaborator share most User columns, but they have slightly different behaviors and privileges. My models currently looks like this:

class User < ActiveRecord::Base

  devise :database_authenticatable, :registerable,
     :recoverable, :rememberable, :trackable, :validatable, :token_authenticatable

  # Setup accessible (or protected) attributes for your model
  attr_accessible :email, :name, :password, :password_confirmation, :remember_me

  before_save :ensure_authentication_token

  [...]

end

class Admin < User
  has_one :account, dependent: :destroy 
  attr_accessible :account_attributes 
  accepts_nested_attributes_for :account
end


class Collaborator < User
  has_one :account
end

class Account < ActiveRecord::Base
  attr_accessible :name
  validates_presence_of :name 
  has_many :projects, dependent: :destroy
  has_many :users
end

The problem aries when I try to authenticate Admins and Collaborators in my ProjectController (and other controllers where I need authentication):

# Causes problem, no one can access anything.
before_filter :authenticate_admin!
before_filter :authenticate_collaborator!

A similar problem I had was with devise's helper methods for ie. current_user, now I have current_admin and current_collaborator, I "solved" that by creating a before filter and method:

def set_current_user
  @current_user = current_admin || current_collaborator
end

Is there a similar or simple solution for my authentication problem with Devise, or would you recommend another approach than Single Table Inheritance, and what would t

Edit
Report

1 Answer

4

Not sure if this is still needed a solution to this...

A more elegant way to have the double authentications could be to do the following:

private

def authenticate!
   :authenticate_admin! || :authenticate_collaborator!
   @current_user = admin_signed_in? ? current_admin : current_collaborator
end

Then call before_filter :authenticate!

If you dont need a universal '@current_user' variable just leave out the second line.

Hope this helps.

answered 2013-06-03T20:36:27.497

Your Answer