I have three model classes: PatientBoard
, Medication
and Customer
, which relates to each other like the following:
PatientBoard
associations do
has_and_belongs_to_many :customers
has_many :medications
end
Medication
associations do
belongs_to :patient_board
end
Customer
associations do
has_many :patient_boards
end
Due to the has_and_belongs_to_many
relationship, my patient_board object looks like this:
{
_id: ObjectId("5e160f235eb3607d57f59341"),
name: "test",
customer_ids: [ObjectId("5db1e6f45eb36059a4d98e7f")]
}
Where the ids from all the customers who have access to that patient board will be inside the customer_ids array.
The problem
When trying to set the permissions to the user, I did it like the following for the PatientBoard
:
can :manage, PatientBoard do |pb|
pb.customer_ids.include? user.id
end
It works for the most part. But the create
method still wouldn't work, so I had to insert the following line too:
can :create, PatientBoard
Now it works normally, but when I tried to do the same for the Medication
it didn't work:
can :manage, Medication do |m|
m.patient_board.customer_ids.include? user.id
end
It throws this error message:
The accessible_by call cannot be used with a block 'can' definition. The SQL cannot be determined for :index Medication
So I tried doing it like this:
can :manage, Medication, patient_board: { customers: { id: user.id } }
That way the error message isn't shown anymore, but neither are the medications. And when trying to create a new medication it throws that error:
undefined method `matches?' for #PatientBoard:0x007f663c38d0e8 Did you mean? _matches? matcher
Which I think that makes sense, since its trying to compare an String value (user.id
) to an array value (customer_ids
)
In resume
How can I check if the user.id
is in the customer_ids
array using the hash of conditions of the CanCanCan?
So, i managed to solve the problem after checking the issue #345 on the CanCan github.
Apparently, i had to provide an sql query to match the medications, so i did it like this:
can [:manage], [Medication], ["#{user.id} in ( select customer_ids from patient_board where id = medications.patient_board.id ) )"] do |t|
t.patient_board.customer_ids.include? user.
end