Ziyan Junaideen
Ziyan Junaideen

Reputation: 3310

Using CanCanCan with views to hide/show content - Advice

This might be an obvious issue for some one good with CanCanCan, but I am finding it hard to wrap my head around it.

I got an application that has many roles around it (campus_rep, campus_manager, operations_manager, admin etc). They all have acces to an 'admin' section but will see different menu options based on their role.

For example:

Extract of ability.rb

if user.role == 'admin'
  can     :manage,  JobApplication
elsif user.role == 'operations_manager'
  can     :manage,  JobApplication,       school_id: user.schools.map(&:id)
elsif ser.role == 'campus_rep'
  # blah but nothing to do with JobApplication
end

I have been thinking to use if can? :manage, Customer but then even 'operations_managers' don't pass it which makes sense.

What is the recommended way to get out of a similar situation?

I tried if can? :manage, Customer.new(school: current_user.schools.first) which kinda works but looks not alright.

I though of doing some thing like adding can :see, JobApplication to both 'admin' and 'operations_managers' and then doing the check like if can? :see, JobApplication.

What is recommended? Is there any better way? Hopefully there is...

Also highly appreciate any advice in the matter

Upvotes: 0

Views: 257

Answers (1)

dcorking
dcorking

Reputation: 1206

Your code mentions JobApplications but your question is mostly about Customers : I'll talk about Customers but the principle is the same for any model.

If I understand you correctly, you aim to pass a collection of customers to your view. But you only want the view to show those customers that your user (say an operations manager) is allowed to manage.

In that case your controller or view template code can filter the customers according to ability. So you would do something like

@customers = Customer.find_each.select { |cstmr| current_user.can? :manage, cstmr }

This will be quite slow if there are a lot of customers, so some programmers will try to bypass cancancan and design a database query instead. For example, you could query the database for all customers belonging to a particular school.

Your main misunderstanding is that you are trying to test abilities based on classes. However, your rules are based on individual objects. This is normal, so the normal way is to test each instance.

Reference: http://www.rubydoc.info/gems/cancancan/1.13.1#2__Check_Abilities___Authorization

Upvotes: 1

Related Questions