0

I'm having problems restricting the data shown to a specific user group using cancan..

My Users have many Products. And Products have many Vouchers.

In my routes.rb I have this:

resources :products do
  resources :vouchers
end

In ability.rb:

 can [:create, :update, :read ], Voucher, :product => { :user_id => user.id }

And in my Voucher controller:

  def index
  ...
   if params[:product_id]
     @voucher = Voucher.find_all_by_product_id(params[:product_id])
   end
  ...
  end

Finally, in my view, I'm trying to display a list of vouchers in a Product group associated with current user.

For example:

  http://localhost:3000/products/eef4e33116a7db/voucher

This lists the vouchers in the product group however, ALL users can see every voucher / product..

I'll assume my abilities are wrong. Help please :)

simonmorley
  • 2,810
  • 4
  • 30
  • 61

2 Answers2

0

Have a look at the can can wiki for fetching records: https://github.com/ryanb/cancan/wiki/Fetching-Records

If you're calling load_and_authorize_resource, you'll either be able to do something similar to one of these two things:

  def index
  ...
   if params[:product_id]
     @vouchers = @vouchers.where(product_id: params[:product_id])
   end
  ...
  end

load_and_authorize_resource should automatically assign the @vouchers instance variable based on the accessible_by parameters for that controller action. If this isn't working, just define it more explicitly:

if params[:product_id]
  @vouchers = Voucher.includes(:product).where(product_id: params[:product_id]).where(product: { user_id: current_user.id })
end
Matthew Lehner
  • 3,967
  • 3
  • 26
  • 35
  • Ok, I'm trying now. Does my ability look ok though? – simonmorley Jun 29 '12 at 15:00
  • Your ability looks fine - the problem you're facing is that you're not using cancan for fetching the records in your controller, instead calling the find method directly on the `Voucher` model. – Matthew Lehner Jun 29 '12 at 15:19
  • ah ok. Have tried the first method but that gives me the same as before. I.e. I can view other users vouchers. Using the second method, I get the same as if I use accessible_by(current_ability) - i.e. no results. – simonmorley Jun 29 '12 at 15:28
0

For anyone else having this issue, I needed to do the following in my vouchers controller:

 @product = Product.accessible_by(current_ability).find(params[:product_id])
 @voucher = @product.vouchers

However, although this did actually block other users from viewing the results, loading the product first with accessible_by led to an exception which required a separate rescue block.

simonmorley
  • 2,810
  • 4
  • 30
  • 61