diff --git a/lib/cancan/mongoid_additions.rb b/lib/cancan/mongoid_additions.rb index 86181c3..eaf6505 100644 --- a/lib/cancan/mongoid_additions.rb +++ b/lib/cancan/mongoid_additions.rb @@ -1,10 +1,9 @@ module CanCan - module Ability # could use alias_method_chain, but it's not worth adding activesupport as a gem dependency alias_method :query_without_mongoid_support, :query def query(action, subject) - if Object.const_defined?(:Mongoid) && subject <= CanCan::MongoidAdditions + if defined?(::Mongoid) && subject <= CanCan::MongoidAdditions query_with_mongoid_support(action, subject) else query_without_mongoid_support(action, subject) @@ -47,7 +46,7 @@ module CanCan # => true class Rule 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 defined?(::Mongoid) && subject.class.include?(::Mongoid::Document) && conditions.any?{|k,v| !k.kind_of?(Symbol)} if conditions.empty? true else @@ -98,7 +97,7 @@ end # Info on monkeypatching Mongoid : # http://log.mazniak.org/post/719062325/monkey-patching-activesupport-concern-and-you#footer -if defined? Mongoid +if defined?(::Mongoid) module Mongoid module Components old_block = @_included_block diff --git a/spec/cancan/mongoid_additions_spec.rb b/spec/cancan/mongoid_additions_spec.rb index 1d5b8a0..7d5309c 100644 --- a/spec/cancan/mongoid_additions_spec.rb +++ b/spec/cancan/mongoid_additions_spec.rb @@ -1,5 +1,5 @@ +require 'mongoid' # require mongoid first so MongoidAdditions are loaded require "spec_helper" -require 'mongoid' class MongoidCategory include Mongoid::Document @@ -38,129 +38,153 @@ Mongoid.configure do |config| end describe CanCan::MongoidAdditions do - before(:each) do - @model_class = MongoidProject - @ability = Object.new - @ability.extend(CanCan::Ability) - end - - after(:each) do - Mongoid.master.collections.select do |collection| - collection.name !~ /system/ - end.each(&:drop) - end - - it "should compare properties on mongoid documents with the conditions hash" 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' - @model_class.create :title => 'Dude' - - @model_class.accessible_by(@ability, :read).entries.should == [] - end - - it "should return the correct records based on the defined ability" do - @ability.can :read, @model_class, :title => "Sir" - sir = @model_class.create :title => 'Sir' - lord = @model_class.create :title => 'Lord' - dude = @model_class.create :title => 'Dude' - - @model_class.accessible_by(@ability, :read).should == [sir] - end - - it "should return everything when the defined ability is manage all" do - @ability.can :manage, :all - sir = @model_class.create :title => 'Sir' - lord = @model_class.create :title => 'Lord' - dude = @model_class.create :title => 'Dude' - - @model_class.accessible_by(@ability, :read).entries.should == [sir, lord, dude] - end - - - describe "Mongoid::Criteria where clause Symbol extensions using MongoDB expressions" do - it "should handle :field.in" do - obj = @model_class.create :title => 'Sir' - @ability.can :read, @model_class, :title.in => ["Sir", "Madam"] - @ability.can?(:read, obj).should == true - @model_class.accessible_by(@ability, :read).should == [obj] - - obj2 = @model_class.create :title => 'Lord' - @ability.can?(:read, obj2).should == false + context "Mongoid not defined" do + before(:all) do + @mongoid_class = Object.send(:remove_const, :Mongoid) 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"]} - mock(@model_class).where(@conditions) {[obj]} - @ability.can :read, @model_class, @conditions - @ability.should be_able_to(: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 + after(:all) do + Object.const_set(:Mongoid, @mongoid_class) end - - it "should handle :field.nin" do - obj = @model_class.create :title => 'Sir' - @ability.can :read, @model_class, :title.nin => ["Lord", "Madam"] - @ability.can?(:read, obj).should == true - @model_class.accessible_by(@ability, :read).should == [obj] - - obj2 = @model_class.create :title => 'Lord' - @ability.can?(:read, obj2).should == false - end - - it "should handle :field.size" do - obj = @model_class.create :titles => ['Palatin', 'Margrave'] - @ability.can :read, @model_class, :titles.size => 2 - @ability.can?(:read, obj).should == true - @model_class.accessible_by(@ability, :read).should == [obj] - - obj2 = @model_class.create :titles => ['Palatin', 'Margrave', 'Marquis'] - @ability.can?(:read, obj2).should == false - end - - it "should handle :field.exists" do - obj = @model_class.create :titles => ['Palatin', 'Margrave'] - @ability.can :read, @model_class, :titles.exists => true - @ability.can?(:read, obj).should == true - @model_class.accessible_by(@ability, :read).should == [obj] - - obj2 = @model_class.create - @ability.can?(:read, obj2).should == false - end - - it "should handle :field.gt" do - obj = @model_class.create :age => 50 - @ability.can :read, @model_class, :age.gt => 45 - @ability.can?(:read, obj).should == true - @model_class.accessible_by(@ability, :read).should == [obj] - - obj2 = @model_class.create :age => 40 - @ability.can?(:read, obj2).should == false + it "should not raise an error for ActiveRecord models" do + @model_class = Class.new(Project) + stub(@model_class).scoped { :scoped_stub } + @model_class.send(:include, CanCan::ActiveRecordAdditions) + @ability = Object.new + @ability.extend(CanCan::Ability) + + @ability.can :read, @model_class + lambda { + @ability.can? :read, @model_class.new + }.should_not raise_error end end + + context "Mongoid defined" do + before(:each) do + @model_class = MongoidProject + @ability = Object.new + @ability.extend(CanCan::Ability) + end - it "should call where with matching ability conditions" do - obj = @model_class.create :foo => {:bar => 1} - @ability.can :read, @model_class, :foo => {:bar => 1} - @model_class.accessible_by(@ability, :read).entries.first.should == obj - end + after(:each) do + Mongoid.master.collections.select do |collection| + collection.name !~ /system/ + end.each(&:drop) + end - it "should not allow to fetch records when ability with just block present" do - @ability.can :read, @model_class do false end - lambda { - @model_class.accessible_by(@ability) - }.should raise_error(CanCan::Error) + it "should compare properties on mongoid documents with the conditions hash" 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' + @model_class.create :title => 'Dude' + + @model_class.accessible_by(@ability, :read).entries.should == [] + end + + it "should return the correct records based on the defined ability" do + @ability.can :read, @model_class, :title => "Sir" + sir = @model_class.create :title => 'Sir' + lord = @model_class.create :title => 'Lord' + dude = @model_class.create :title => 'Dude' + + @model_class.accessible_by(@ability, :read).should == [sir] + end + + it "should return everything when the defined ability is manage all" do + @ability.can :manage, :all + sir = @model_class.create :title => 'Sir' + lord = @model_class.create :title => 'Lord' + dude = @model_class.create :title => 'Dude' + + @model_class.accessible_by(@ability, :read).entries.should == [sir, lord, dude] + end + + + describe "Mongoid::Criteria where clause Symbol extensions using MongoDB expressions" do + it "should handle :field.in" do + obj = @model_class.create :title => 'Sir' + @ability.can :read, @model_class, :title.in => ["Sir", "Madam"] + @ability.can?(:read, obj).should == true + @model_class.accessible_by(@ability, :read).should == [obj] + + obj2 = @model_class.create :title => 'Lord' + @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"]} + mock(@model_class).where(@conditions) {[obj]} + @ability.can :read, @model_class, @conditions + @ability.should be_able_to(: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"] + @ability.can?(:read, obj).should == true + @model_class.accessible_by(@ability, :read).should == [obj] + + obj2 = @model_class.create :title => 'Lord' + @ability.can?(:read, obj2).should == false + end + + it "should handle :field.size" do + obj = @model_class.create :titles => ['Palatin', 'Margrave'] + @ability.can :read, @model_class, :titles.size => 2 + @ability.can?(:read, obj).should == true + @model_class.accessible_by(@ability, :read).should == [obj] + + obj2 = @model_class.create :titles => ['Palatin', 'Margrave', 'Marquis'] + @ability.can?(:read, obj2).should == false + end + + it "should handle :field.exists" do + obj = @model_class.create :titles => ['Palatin', 'Margrave'] + @ability.can :read, @model_class, :titles.exists => true + @ability.can?(:read, obj).should == true + @model_class.accessible_by(@ability, :read).should == [obj] + + obj2 = @model_class.create + @ability.can?(:read, obj2).should == false + end + + it "should handle :field.gt" do + obj = @model_class.create :age => 50 + @ability.can :read, @model_class, :age.gt => 45 + @ability.can?(:read, obj).should == true + @model_class.accessible_by(@ability, :read).should == [obj] + + obj2 = @model_class.create :age => 40 + @ability.can?(:read, obj2).should == false + end + end + + it "should call where with matching ability conditions" do + obj = @model_class.create :foo => {:bar => 1} + @ability.can :read, @model_class, :foo => {:bar => 1} + @model_class.accessible_by(@ability, :read).entries.first.should == obj + end + + it "should not allow to fetch records when ability with just block present" do + @ability.can :read, @model_class do false end + lambda { + @model_class.accessible_by(@ability) + }.should raise_error(CanCan::Error) + end end end