refactoring query.conditions

This commit is contained in:
Ryan Bates
2010-07-20 16:00:22 -07:00
parent 964a4765b1
commit e098ddaacd
7 changed files with 100 additions and 108 deletions

View File

@@ -9,9 +9,9 @@ describe CanCan::ActiveRecordAdditions do
@ability.extend(CanCan::Ability)
end
it "should call where(:id => nil) when no ability is defined so no records are found" do
stub(@model_class).where(:id => nil).stub!.joins(nil) { :no_where }
@model_class.accessible_by(@ability, :read).should == :no_where
it "should call where('true=false') when no ability is defined so no records are found" do
stub(@model_class).where('true=false').stub!.joins(nil) { :no_match }
@model_class.accessible_by(@ability, :read).should == :no_match
end
it "should call where with matching ability conditions" do
@@ -44,7 +44,7 @@ describe CanCan::ActiveRecordAdditions do
stub(@model_class).scoped( :conditions => condition, :joins => joins ) { :found_records }
end
end
# @ability.sql_conditions(:read, @model_class).should == '(too.car=1 AND too.far.bar=1) OR (foo.bar=1)'
# @ability.conditions(:read, @model_class).should == '(too.car=1 AND too.far.bar=1) OR (foo.bar=1)'
# @ability.association_joins(:read, @model_class).should == [{:too => [:far]}, :foo]
@model_class.accessible_by(@ability).should == :found_records
end

View File

@@ -6,72 +6,70 @@ describe CanCan::Query do
@ability.extend(CanCan::Ability)
end
it "should return array of behavior and conditions for a given ability" do
@ability.can :read, Person, :first => 1, :last => 3
@ability.query(:show, Person).conditions.should == [[true, {:first => 1, :last => 3}]]
end
it "should raise an exception when a block is used on condition, and no hash" do
@ability.can :read, Person do |a|
true
end
lambda { @ability.query(:show, Person).conditions }.should raise_error(CanCan::Error, "Cannot determine SQL conditions or joins from block for :show Person")
end
it "should return an array with just behavior for conditions when there are no conditions" do
@ability.can :read, Person
@ability.query(:show, Person).conditions.should == [ [true, {}] ]
end
it "should return false when performed on an action which isn't defined" do
@ability.query(:foo, Person).conditions.should == false
it "should have false conditions if no abilities match" do
@ability.query(:destroy, Person).conditions.should == "true=false"
end
it "should return hash for single `can` definition" do
@ability.can :read, Person, :blocked => false, :user_id => 1
@ability.query(:read, Person).sql_conditions.should == { :blocked => false, :user_id => 1 }
@ability.query(:read, Person).conditions.should == { :blocked => false, :user_id => 1 }
end
it "should return `sql` for single `can` definition in front of default `cannot` condition" do
it "should merge multiple can definitions into single SQL string joining with OR" do
@ability.can :read, Person, :blocked => false
@ability.can :read, Person, :admin => true
@ability.query(:read, Person).conditions.should == "(admin=true) OR (blocked=false)"
end
it "should merge multiple can definitions into single SQL string joining with OR and AND" do
@ability.can :read, Person, :blocked => false, :active => true
@ability.can :read, Person, :admin => true
@ability.query(:read, Person).conditions.should orderlessly_match("(blocked=false AND active=true) OR (admin=true)")
end
it "should merge multiple can definitions into single SQL string joining with OR and AND" do
@ability.can :read, Person, :blocked => false, :active => true
@ability.can :read, Person, :admin => true
@ability.query(:read, Person).conditions.should orderlessly_match("(blocked=false AND active=true) OR (admin=true)")
end
it "should return false conditions for cannot clause" do
@ability.cannot :read, Person
@ability.query(:read, Person).conditions.should == "true=false"
end
it "should return SQL for single `can` definition in front of default `cannot` condition" do
@ability.cannot :read, Person
@ability.can :read, Person, :blocked => false, :user_id => 1
result = @ability.query(:read, Person).sql_conditions
result.should include("blocked=false")
result.should include(" AND ")
result.should include("user_id=1")
end
it "should return `true condition` for single `can` definition in front of default `can` condition" do
result = @ability.query(:read, Person).conditions.should orderlessly_match("blocked=false AND user_id=1")
end
it "should return true condition for single `can` definition in front of default `can` condition" do
@ability.can :read, Person
@ability.can :read, Person, :blocked => false, :user_id => 1
@ability.query(:read, Person).sql_conditions.should == 'true=true'
@ability.query(:read, Person).conditions.should == 'true=true'
end
it "should return `false condition` for single `cannot` definition" do
it "should return false condition for single `cannot` definition" do
@ability.cannot :read, Person, :blocked => true, :user_id => 1
@ability.query(:read, Person).sql_conditions.should == 'true=false'
@ability.query(:read, Person).conditions.should == 'true=false'
end
it "should return `false condition` for single `cannot` definition in front of default `cannot` condition" do
@ability.cannot :read, Person
@ability.cannot :read, Person, :blocked => true, :user_id => 1
@ability.query(:read, Person).sql_conditions.should == 'true=false'
@ability.query(:read, Person).conditions.should == 'true=false'
end
it "should return `not (sql)` for single `cannot` definition in front of default `can` condition" do
@ability.can :read, Person
@ability.cannot :read, Person, :blocked => true, :user_id => 1
result = @ability.query(:read, Person).sql_conditions
result.should include("not ")
result.should include("blocked=true")
result.should include(" AND ")
result.should include("user_id=1")
result = @ability.query(:read, Person).conditions.should orderlessly_match("not (blocked=true AND user_id=1)")
end
it "should return appropriate sql conditions in complex case" do
@@ -80,8 +78,8 @@ describe CanCan::Query do
@ability.can :update, Person, :manager_id => 1
@ability.cannot :update, Person, :self_managed => true
@ability.query(:update, Person).sql_conditions.should == 'not (self_managed=true) AND ((manager_id=1) OR (id=1))'
@ability.query(:manage, Person).sql_conditions.should == {:id=>1}
@ability.query(:read, Person).sql_conditions.should == 'true=true'
@ability.query(:update, Person).conditions.should == 'not (self_managed=true) AND ((manager_id=1) OR (id=1))'
@ability.query(:manage, Person).conditions.should == {:id=>1}
@ability.query(:read, Person).conditions.should == 'true=true'
end
end

13
spec/matchers.rb Normal file
View File

@@ -0,0 +1,13 @@
Spec::Matchers.define :orderlessly_match do |original_string|
match do |given_string|
original_string.bytes.sum == given_string.bytes.sum
end
failure_message_for_should do |given_string|
"expected \"#{given_string}\" to have the same characters as \"#{original_string}\""
end
failure_message_for_should_not do |given_string|
"expected \"#{given_string}\" not to have the same characters as \"#{original_string}\""
end
end

View File

@@ -4,6 +4,7 @@ require 'active_support'
require 'active_record'
require 'action_controller'
require 'action_view'
require 'matchers'
require 'cancan'
require 'cancan/matchers'