allow Active Record scope to be passed as Ability conditions - closes #257
This commit is contained in:
parent
80f1ab20fb
commit
f9b181af05
|
@ -55,7 +55,9 @@ module CanCan
|
|||
end
|
||||
|
||||
def database_records
|
||||
if @model_class.respond_to?(:where) && @model_class.respond_to?(:joins)
|
||||
if override_scope
|
||||
override_scope
|
||||
elsif @model_class.respond_to?(:where) && @model_class.respond_to?(:joins)
|
||||
@model_class.where(conditions).joins(joins)
|
||||
else
|
||||
@model_class.scoped(:conditions => conditions, :joins => joins)
|
||||
|
@ -64,6 +66,18 @@ module CanCan
|
|||
|
||||
private
|
||||
|
||||
def override_scope
|
||||
conditions = @rules.map(&:conditions).compact
|
||||
if conditions.any? { |c| c.kind_of?(ActiveRecord::Relation) }
|
||||
if conditions.size == 1
|
||||
conditions.first
|
||||
else
|
||||
rule = @rules.detect { |rule| rule.conditions.kind_of?(ActiveRecord::Relation) }
|
||||
raise Error, "Unable to merge an Active Record scope with other conditions. Instead use a hash or SQL for #{rule.actions.first} #{rule.subjects.first} ability."
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def merge_conditions(sql, conditions_hash, behavior)
|
||||
if conditions_hash.blank?
|
||||
behavior ? true_sql : false_sql
|
||||
|
|
|
@ -3,7 +3,7 @@ module CanCan
|
|||
# it holds the information about a "can" call made on Ability and provides
|
||||
# helpful methods to determine permission checking and conditions hash generation.
|
||||
class Rule # :nodoc:
|
||||
attr_reader :base_behavior, :actions, :conditions
|
||||
attr_reader :base_behavior, :subjects, :actions, :conditions
|
||||
attr_writer :expanded_actions
|
||||
|
||||
# The first argument when initializing is the base_behavior which is a true/false
|
||||
|
|
|
@ -110,10 +110,25 @@ if ENV["MODEL_ADAPTER"].nil? || ENV["MODEL_ADAPTER"] == "active_record"
|
|||
@ability.can :read, Article, :published => true
|
||||
@ability.can :read, Article, ["secret=?", true]
|
||||
article1 = Article.create!(:published => true, :secret => false)
|
||||
article2 = Article.create!(:published => true, :secret => true)
|
||||
article3 = Article.create!(:published => false, :secret => true)
|
||||
article4 = Article.create!(:published => false, :secret => false)
|
||||
Article.accessible_by(@ability).should == [article1, article2, article3]
|
||||
end
|
||||
|
||||
it "should allow a scope for conditions" do
|
||||
@ability.can :read, Article, Article.where(:secret => true)
|
||||
article1 = Article.create!(:secret => true)
|
||||
article2 = Article.create!(:secret => false)
|
||||
Article.accessible_by(@ability).should == [article1]
|
||||
end
|
||||
|
||||
it "should raise an exception when trying to merge scope with other conditions" do
|
||||
@ability.can :read, Article, :published => true
|
||||
@ability.can :read, Article, Article.where(:secret => true)
|
||||
lambda { Article.accessible_by(@ability) }.should raise_error(CanCan::Error, "Unable to merge an Active Record scope with other conditions. Instead use a hash or SQL for read Article ability.")
|
||||
end
|
||||
|
||||
it "should not allow to fetch records when ability with just block present" do
|
||||
@ability.can :read, Article do
|
||||
false
|
||||
|
|
Loading…
Reference in New Issue
Block a user