Last Updated: 29 Aug 2013 18:54 EST
I have the following module defined and then included into my model. I am using the rolify gem to give my users roles.
module Permissions::Offer
extend ActiveSupport::Concern
included do
# `user` is a context of security
protect do |user, offer|
# Admins can retrieve anything
if user.has_role? :administrator
scope { all }
# ... and view, create, update, or destroy anything
can :view
can :create
can :update
can :destroy
elsif user.present?
# Allow to read any field
can :view
can :create
# Checks offered_by_id keeping possible nil in mind
# Allow sellers to modify/delete their own offers
if offer.try(:offered_by_id) == user.id
can :update
can :destroy
end
else
# Guests can't read the text
cannot :view
end
end
end
end
What I am experiencing is that when I do the following...
respond_with Offer.restrict!(current_user)
It queries the roles table for every offer that is returned. Is there anyway to have it not make this request repeatedly when requesting a list of offers? I'm sure I could cache the response to avoid the database hit, but I'd rather it not hit the cache either.
If I open a rails console and do the following I get the same result:
current_user = User.first
Offer.restrict!(current_user).to_a
I have installed the bullet gem to see if it considers it an N+1 query, and it doesn't not detect it. I believe because the included gets called every time a new instance of offer gets created it fires off this call to verify permissions. That coupled with the fact that rolify does not cache it's user role checks for any length of time makes this less than ideal. I suppose rolify does this to allow for the changing of roles on the fly without having to deal with clearing the cache. As of now the only way I can see to solve this is to implement caching of my own.
I opened an issue with rolify to see if they are interested in creating a more permanent solution. For anyone else that encounters this, here's what I did int eh meantime.
This doesn't do everything the real method does.. but it suits my purposes.
Here is a link to the source for anyone that wishes to implement something like this on all the methods.
https://github.com/EppO/rolify/blob/master/lib/rolify/role.rb