Version 1.5 – June 12, 2008
role_requirement first assumes that the controller is accessible to everyone.
Each require_role line serves to add one or more required roles before executing actions within the controller. IE:
require_role "admin" # Require that the current_user must have role admin # before executing any action within this controller.
role_requirement accepts several methods as an options hash of key/value pairs. These methods work like clauses that limit the require_role line.
:for – Evaluate this role requirement before executing ONLY the following actions in this controller…
* :for_all_except – Evaluate this role requirement before executing ALL actions in this controller EXCEPT the following…
(note: :only and :except also work, similarly to before_filter)
These methods can be thought of as telling role_requirement when to evaluate current_user’s roles.
# Anytime an action is called, require the role admin in order to execute, # EXCEPT when index is called. So, index passes through this require_role # line allowing anyone to access it, ALL other actions are evaluated against # the specified role(s). require_role "admin", :for_all_except => :index # Means, "Evaluate current_user's role(s) ONLY when index is called... and # require admin in order to execute index." So, every action except index # passes through this require_role line, ONLY index is evaluated. require_role "admin", :for => :index
How require_role Lines Work In Combination
Each line serves as an additional requirement to any other lines in the controller… like AND… not OR.
require_role "admin" require_role "executive" # This means that role_requirement will look for BOTH roles for EVERY action # in the controller, i. e. current_user must have both admin and executive # roles to do anything in this controller. require_role "admin" require_role "executive", :except => [:index] # This means that admin can access only index and executive can access # everything in the controller except index. # The controller requires admin for every action AND looks for executive in # order to execute every action except index. (Probably not a very useful # configuration!) require_role "admin" require_role "executive", :only => [:create, :update, :edit, :destroy] # This means that admin can access the entire controller and executive is # required only for index. # The controller always requires admin and requires executive only when # index is called. Useful for allowing only executive to call certain, more # restricted, actions, for example.
role_requirement accepts arrays of roles and/or actions. When more than one role name or action name is passed, they work like “OR” in the requirement phrase.
# current_user can do anything in this controller if they have either role, # admin OR executive. require_role ["admin", "executive"] # The role admin is required to perform all actions in this controller # EXCEPT list or show. So, anyone can list and show. admin can do anything. require_role "admin", :except => [:list, :show] # The role admin is required to perform ONLY delete OR edit. Other actions # are not evaluated. So, only admin can delete or edit. Others can do # anything other than delete or edit. require_role "admin", :only => [:delete, :edit]
role_requirement’s generator will automatically add a method to your user model, User#has_role?
This method, by default, always returns true for the role named “admin.” This makes it easy to create a role that can access all actions, just name it “admin.”
# Allow finance to access every action but delete. Admin can access # everything, including delete. require_role :finance require_role :admin, :only => :delete # Explanation: Finance can access the entire controller (and so can admin # because admin always returns true for every role) AND admin is required to # execute only the delete action.
If you don’t want this behavior, comment out the line that causes admin to always return true:
def has_role?(role_in_question) @_list ||= self.roles.collect(&:name) # return true if @_list.include?("admin") #This is the culprit. (@_list.include?(role_in_question.to_s) ) end
You can also change the name of the “all access” role here. You can use any name that makes sense to you.
If you use strings as keys for the options hash, it will throw an error. ie:
# throws an error require_role "admin", "only" => "index" # works just fine require_role "admin", :only => "index"
RoleRequirement does not care if the values are symbols or strings, regarding action names.
require_role "admin", :only => "index" require_role "admin", :only => :index
Roles are passed to User#has_role? exactly as specified. By default, RoleRequirement generates this method to not care. If you customize User#has_role? in such a way that it does care, then you’ll have problems.
# ultimately calls User#has_role?("admin") require_role "admin", :only => :index # ultimately calls User#has_role?(:admin) require_role :admin, :only => :index