Pundit Scope and has_many through
Hi!
I can use a little help to get on the right track.
I have 3 models
class User < ActiveRecord::Base
has_many :associations
has_many :items, through: :associations
end
class Item < ActiveRecord::Base
has_many :associations
has_many :users, through: :associations
end
class Association < ActiveRecord::Base
belongs_to :user
belongs_to :item
end
Now i want to allow my users only to view and edit the item if they have a link trough associations.
so in my ItemPolicy i have the following scope
class Scope < Scope
def resolve
if user.admin?
scope.all
else
scope.where(:company_id => user.associations.select(:item_id))
end
end
end
I setup my items_controller
def index
@items = policy_scope(Item.includes(:company).all)
authorize @items
end
and this works. i only see the items where i have a association. Now i want to prevent users to edit the urllike myapp.com/item/2 and still be able to view item 2 if there is no association.
So i setup my show in the controller:
def show
@item = policy_scope(Item.find(params[:id]))
authorize @item
end
but now i get undefined method `where' error. why does the same thing work for index and not for show?
any ideas?
also i would like your opinion if this is the right way to go.
I think that's because on the index you want an array of records, but on show you just want a single record.
When you pass in the array into policy_scope, it's going to call the .where(company_id: X)
method on it. This works when you return Item.all
but when you pass in just an Item record, that does not have a where method because it's a single instance of the Item class.
In your show
action, you can change it to:
def show
@item = Item.find(params[:id])
authorize @item
end
And this will load the record and Pundit will know to authorize it against the right method in the policy without hitting the Scope.