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 that be?
My goal is, 1. when new users signs up, they become Admins, when they create their account, an Account model is also created. 2. The new (Admin) user can then invite additional users to the Account, which will be Collaborators. 3. Admins and Collaborators should have different privileges. Collaborators won't create new "Accounts" when they sign up (company could be a better name for my Account model) so Admin and Collaborators will need slightly different forms for signing up and editing.
Thanks.
Update
I kinda "solved" it by creating a similar before filter:
def authenticate!
if @current_user == current_admin
:authenticate_admin!
elsif @current_user == current_collaborator
:authenticate_collaborator!
end
end
Suggestions on possibly more elegant solutions would still be appreciated.