Method: CanCan::Ability#can?

Defined in:
lib/cancan/ability.rb

#can?(action, subject, attribute = nil, *extra_args) ⇒ Boolean

Check if the user has permission to perform a given action on an object.

can? :destroy, @project

You can also pass the class instead of an instance (if you don’t have one handy).

can? :create, Project

Nested resources can be passed through a hash, this way conditions which are dependent upon the association will work when using a class.

can? :create, @category => Project

You can also pass multiple objects to check. You only need to pass a hash following the pattern { :any => [many subjects] }. The behaviour is check if there is a permission on any of the given objects.

can? :create, {:any => [Project, Rule]}

Any additional arguments will be passed into the “can” block definition. This can be used to pass more information about the user’s request for example.

can? :create, Project, request.remote_ip

can :create, Project do |project, remote_ip|
  # ...
end

Not only can you use the can? method in the controller and view (see ControllerAdditions), but you can also call it directly on an ability instance.

ability.can? :destroy, @project

This makes testing a user’s abilities very easy.

def test "user can only destroy projects which he owns"
  user = User.new
  ability = Ability.new(user)
  assert ability.can?(:destroy, Project.new(:user => user))
  assert ability.cannot?(:destroy, Project.new)
end

Also see the RSpec Matchers to aid in testing.

Returns:

  • (Boolean)


74
75
76
77
78
79
80
81
# File 'lib/cancan/ability.rb', line 74

def can?(action, subject, attribute = nil, *extra_args)
  match = extract_subjects(subject).lazy.map do |a_subject|
    relevant_rules_for_match(action, a_subject).detect do |rule|
      rule.matches_conditions?(action, a_subject, attribute, *extra_args) && rule.matches_attributes?(attribute)
    end
  end.reject(&:nil?).first
  match ? match.base_behavior : false
end