can? should only go to db if there are mongoid criteria in the conditions.
Easier to just do a simple comparison on the object in memory than to search the database. Also this allows method calls and other attributes that might not be found in the database.
This commit is contained in:
parent
dbcd93e095
commit
f6aaa581ef
|
@ -10,7 +10,7 @@ Gem::Specification.new do |s|
|
|||
s.files = Dir["{lib,spec}/**/*", "[A-Z]*", "init.rb"] - ["Gemfile.lock"]
|
||||
s.require_path = "lib"
|
||||
|
||||
s.add_development_dependency 'rspec', '~> 2.0.0.beta.22'
|
||||
s.add_development_dependency 'rspec', '~> 2.1.0'
|
||||
s.add_development_dependency 'rails', '~> 3.0.0'
|
||||
s.add_development_dependency 'rr', '~> 0.10.11' # 1.0.0 has respond_to? issues: http://github.com/btakita/rr/issues/issue/43
|
||||
s.add_development_dependency 'supermodel', '~> 0.1.4'
|
||||
|
@ -18,7 +18,7 @@ Gem::Specification.new do |s|
|
|||
s.add_development_dependency 'mongoid', '~> 2.0.0.beta.19'
|
||||
s.add_development_dependency 'bson_ext', '~> 1.1'
|
||||
|
||||
s.add_development_dependency 'ruby-debug'
|
||||
# s.add_development_dependency 'ruby-debug'
|
||||
|
||||
s.rubyforge_project = s.name
|
||||
s.required_rubygems_version = ">= 1.3.4"
|
||||
|
|
|
@ -36,37 +36,28 @@ module CanCan
|
|||
end
|
||||
|
||||
# customize to handle Mongoid queries in ability definitions conditions
|
||||
class CanDefinition
|
||||
def matches_conditions_hash?(subject, conditions = @conditions)
|
||||
if subject.class.include?(Mongoid::Document) # Mongoid Criteria are simpler to check than normal conditions hashes
|
||||
if conditions.empty? # When no conditions are given, true should be returned.
|
||||
# Mongoid Criteria are simpler to check than normal conditions hashes
|
||||
# When no conditions are given, true should be returned.
|
||||
# The default CanCan behavior relies on the fact that conditions.all? will return true when conditions is empty
|
||||
# The way ruby handles all? for empty hashes can be unexpected:
|
||||
# {}.all?{|a| a == 5}
|
||||
# => true
|
||||
# {}.all?{|a| a != 5}
|
||||
# => true
|
||||
class CanDefinition
|
||||
def matches_conditions_hash_with_mongoid_subject?(subject, conditions = @conditions)
|
||||
if subject.class.include?(Mongoid::Document) && conditions.any?{|k,v| !k.kind_of?(Symbol)}
|
||||
if conditions.empty?
|
||||
true
|
||||
else
|
||||
subject.class.where(conditions).include?(subject) # just use Mongoid's where function
|
||||
end
|
||||
else
|
||||
conditions.all? do |name, value|
|
||||
attribute = subject.send(name)
|
||||
if value.kind_of?(Hash)
|
||||
if attribute.kind_of? Array
|
||||
attribute.any? { |element| matches_conditions_hash? element, value }
|
||||
else
|
||||
matches_conditions_hash? attribute, value
|
||||
end
|
||||
elsif value.kind_of?(Array) || value.kind_of?(Range)
|
||||
value.include? attribute
|
||||
else
|
||||
attribute == value
|
||||
end
|
||||
end
|
||||
matches_conditions_hash_without_mongoid_subject? subject, conditions
|
||||
end
|
||||
end
|
||||
alias_method :matches_conditions_hash_without_mongoid_subject?, :matches_conditions_hash?
|
||||
alias_method :matches_conditions_hash?, :matches_conditions_hash_with_mongoid_subject?
|
||||
end
|
||||
|
||||
|
||||
|
|
|
@ -50,6 +50,12 @@ describe CanCan::MongoidAdditions do
|
|||
end.each(&:drop)
|
||||
end
|
||||
|
||||
it "should compare properties on mongoid documents with the " do
|
||||
model = @model_class.new
|
||||
@ability.can :read, @model_class, :id => model.id
|
||||
@ability.should be_able_to :read, model
|
||||
end
|
||||
|
||||
it "should return [] when no ability is defined so no records are found" do
|
||||
@model_class.create :title => 'Sir'
|
||||
@model_class.create :title => 'Lord'
|
||||
|
@ -88,6 +94,22 @@ describe CanCan::MongoidAdditions do
|
|||
@ability.can?(:read, obj2).should == false
|
||||
end
|
||||
|
||||
describe "activates only when there are Criteria in the hash" do
|
||||
it "Calls where on the model class when there are criteria" do
|
||||
obj = @model_class.create :title => 'Bird'
|
||||
@conditions = {:title.nin => ["Fork", "Spoon"]}
|
||||
@model_class.should_receive(:where).with(@conditions) {[obj]}
|
||||
@ability.can :read, @model_class, @conditions
|
||||
@ability.can?(:read, obj)
|
||||
end
|
||||
it "Calls the base version if there are no mongoid criteria" do
|
||||
obj = @model_class.new :title => 'Bird'
|
||||
@conditions = {:id => obj.id}
|
||||
@ability.can :read, @model_class, @conditions
|
||||
@ability.should be_able_to(:read, obj)
|
||||
end
|
||||
end
|
||||
|
||||
it "should handle :field.nin" do
|
||||
obj = @model_class.create :title => 'Sir'
|
||||
@ability.can :read, @model_class, :title.nin => ["Lord", "Madam"]
|
||||
|
|
|
@ -5,9 +5,11 @@ require 'supermodel' # shouldn't Bundler do this already?
|
|||
require 'active_support/all'
|
||||
require 'matchers'
|
||||
require 'cancan/matchers'
|
||||
require 'mongoid'
|
||||
require 'active_support'
|
||||
|
||||
RSpec.configure do |config|
|
||||
config.mock_with :rr
|
||||
config.mock_with :rspec
|
||||
config.before(:each) do
|
||||
Project.delete_all
|
||||
Category.delete_all
|
||||
|
|
Loading…
Reference in New Issue
Block a user