Reputation: 1
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
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