harish bhatt
harish bhatt

Reputation: 1

Rails 5 cancancan defining ability with multiple condition and checking ability with single condition doesnt work

Given the following scenario

user.rb

class User < ApplicationRecord
  has_many :enrolments, dependent: :destroy
  has_many :teams, through: :enrolments
end

team.rb

class Team < ApplicationRecord
  has_and_belongs_to_many :coaches, class_name: "User", join_table: "teams_coaches"
end

ability.rb

if user.canrole == "coach"
  can :read, User, canrole: "player", teams: { coaches: { id: user.id } }
end

I have differentiated the roles of user by a column in user table. I need the coach to only see the players for the team which he is coaching. The given rule is successfully working while I use the accessible_by method on index method User.accessible_by(current_ability) it gives me only those players which coach has access to.

but the following is not working properly. can?(:index, User.new(canrole: 'player')) this block of code is used by me to display a navigation menu item called 'players' for a coach user.

Expected Behaviour

The can?(:index, User.new(canrole: 'player')) should return true, as the coach has access to a few players.

Actual Behaviour

The can?(:index, User.new(canrole: 'player')) is returning false


This is somewhat similar to https://github.com/CanCanCommunity/cancancan/blob/develop/docs/Checking-Abilities.md#checking-with-class

where we define the ability rule with a hash, but we check the rule without providing the condition and still we get true in return, because the user has access to at least one project

can :read, Project, :priority => 3
can? :read, Project # returns true

so the same even though we have defined the ability rule with multiple conditions and we are checking the rule with only one condition, it should return true, because one of the conditions of rule is true while checking with instance.


The summary is, the rule is defined with hash of conditions where has contains multiple conditions, but while I check I am checking with only one attribute for using it to check whether I should display 'players' in the navigation menu or not. So seems like if a rule is defined with multiple conditions we can not just check with only one condition.

Upvotes: 0

Views: 778

Answers (1)

coorasse
coorasse

Reputation: 5528

The action can? :index can only be performed on the Class level and is usually used as User.accessible_by(current_ability) which checks the action :index by default.

If you want to know "is there at least one player I can coach?" you need to do

User.accessible_by(current_ability).any?

Upvotes: 0

Related Questions