I am using Ryan Bate's CanCan gem to define abilities and some basic functionality is failing. I have a Product model and Products controller where my index action looks like this:
def index
@req_host_w_port = request.host_with_port
@products = Product.accessible_by(current_ability, :index)
end
I get an error when I try to retrieve the products with the accessible_by
method, I get this error:
Cannot determine SQL conditions or joins from block for :index Product(id: integer, secret: string, context_date: datetime, expiration_date: datetime, blurb: text, created_at: datetime, updated_at: datetime, owner_id: integer, product_type_id: integer, approved_at: datetime)
My ability class looks like this:
can :index, Product do |product|
product && !!product.approved_at
end
This seems like a very simple example so I am surprised it is failing and wondering if I am overlooking something simple (i.e. staring at my code for too long).
I did probe a bit more and ran a simple test. If you look at the code below, one example works fine and one fails where they should actually do the same exact thing.
# This works
can :index, Product, :approved_at => nil
# This fails
can :index, Product do |product|
product && product.approved_at.nil?
end
So the problem seems to be in the way CanCan is processing these blocks. I dove deeper into the library and found where the error was raised - in CanCan's ability class definition:
def relevant_can_definitions_for_query(action, subject)
relevant_can_definitions(action, subject).each do |can_definition|
if can_definition.only_block?
raise Error, "Cannot determine SQL conditions or joins from block for #{action.inspect} #{subject.inspect}"
end
end
end
So I checked out what this only_block?
method is. The method returns true if a can definition has a block but no conditions which makes no sense to me because the whole point of the block is to define the conditions within the block when they are too complicated for the following syntax:
can :manage, [Account], :account_manager_id => user.id
Any insight on this issue would be great! I also filed an issue on the CanCan github page but I'm getting to the point where I may need to ditch the library. However, I understand that many people are using CanCan successfully and this is such basic functionality I think I must be doing something wrong. Especially since the git repo was updated 3 days ago and Ryan Bates mentions Rails 3 support in the README.
Thanks!