Exclude with scope for index action from can(:manage, :all)
Steps to reproduce
Define two rules:
can :manage, :all
cannot(
%i[index retrieve],
Model, Model.from_sandbox
) do ||
m.sandbox?
end
When accessing the index action, I receive the following error
Unable to merge an Active Record scope with other conditions. Instead use a hash or SQL for index Model ability.
from following method
91: def override_scope
92: conditions = @compressed_rules.map(&:conditions).compact
93: return unless conditions.any? { |c| c.is_a?(ActiveRecord::Relation) }
94: return conditions.first if conditions.size == 1
95:
96: raise_override_scope_error
97: end
Because @compressed_rules in ActiveRecord5Adapter is set as follows:
[5] pry(#<CanCan::ModelAdapters::ActiveRecord5Adapter>)> @compressed_rules
=> [#<CanCan::Rulecannot [:index, :retrieve], [Model(<attributes>)], [], {"type"=>["Model"]}>,
#<CanCan::Rulecan [:manage], [:all], [], {}>]
the override_scope method would succeed, if only one condition exists. But the rules defined above are not merged?
Expected behavior
cannot with scope should overwrite can :manage, :all for a specific model for the index action.
Actual behavior
It raises the error mentioned above
System configuration
Rails version: 5.2.3 Ruby version: 2.6.4p104 (2019-08-28 revision 67798) [x86_64-linux] CanCanCan version 3.0.1
Thanks in advance! Best regards, Lukas
It seems that overriding doesn't work with scopes at all. Is that right? Did i missed this fact in the documentation?
I'm also seeing this issue.
class Book < AcrtiveRecord::Base
scope :unpublished, -> { where(:published => false) }
end
class Ability
include CanCan::Ability
def initialize(user)
can :manage, :all
cannot :read, Book.unpublished do |book|
book.published == false
end
end
end
> Book.accessible_by(Ability.new(User.new), :read).to_sql
=> "SELECT \"books\".* FROM \"books\" WHERE (TRUE=FALSE)"
... btw, I tried to create a test using your gist, but when running main.rb, it throws this error:
CanCan::NotImplemented: This model adapter does not support fetching records from the database.