From 6d39b0ae0783dde3e93d8f21c87ef3bdb8f1bfa9 Mon Sep 17 00:00:00 2001 From: Emmanuel Gomez Date: Fri, 29 Apr 2011 00:30:30 -0700 Subject: [PATCH 1/3] Use dkubb's suggestion for evaluating conditions against a Resource. --- lib/cancan/model_adapters/data_mapper_adapter.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/cancan/model_adapters/data_mapper_adapter.rb b/lib/cancan/model_adapters/data_mapper_adapter.rb index 9d456d2..38ba023 100644 --- a/lib/cancan/model_adapters/data_mapper_adapter.rb +++ b/lib/cancan/model_adapters/data_mapper_adapter.rb @@ -10,7 +10,8 @@ module CanCan end def self.matches_conditions_hash?(subject, conditions) - subject.class.all(:conditions => conditions).include?(subject) # TODO don't use a database query here for performance and other instances + collection = DataMapper::Collection.new(subject.query, [ subject ]) + !!collection.first(conditions) end def database_records From d6851debd44bcd7851a346a08085eeb228095e9e Mon Sep 17 00:00:00 2001 From: Emmanuel Gomez Date: Fri, 29 Apr 2011 00:46:38 -0700 Subject: [PATCH 2/3] Fix pending spec for DataMapper adapter. --- .../model_adapters/data_mapper_adapter.rb | 19 ++++++++----------- .../data_mapper_adapter_spec.rb | 1 - 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/lib/cancan/model_adapters/data_mapper_adapter.rb b/lib/cancan/model_adapters/data_mapper_adapter.rb index 38ba023..9060b97 100644 --- a/lib/cancan/model_adapters/data_mapper_adapter.rb +++ b/lib/cancan/model_adapters/data_mapper_adapter.rb @@ -15,19 +15,16 @@ module CanCan end def database_records - scope = @model_class.all(:conditions => ["0=1"]) - conditions.each do |condition| - scope += @model_class.all(:conditions => condition) - end + scope = @model_class.all(:conditions => ["0 = 1"]) + cans, cannots = @rules.partition { |r| r.base_behavior } + # apply unions first, then differences. this mean cannot overrides can + cans.each { |r| scope += @model_class.all(:conditions => r.conditions) } + cannots.each { |r| scope -= @model_class.all(:conditions => r.conditions) } scope end - - def conditions - @rules.map(&:conditions) - end - end - end -end + end # class DataMapper + end # module ModelAdapters +end # module CanCan DataMapper::Model.class_eval do include CanCan::ModelAdditions::ClassMethods diff --git a/spec/cancan/model_adapters/data_mapper_adapter_spec.rb b/spec/cancan/model_adapters/data_mapper_adapter_spec.rb index 924b65f..e2eb1f8 100644 --- a/spec/cancan/model_adapters/data_mapper_adapter_spec.rb +++ b/spec/cancan/model_adapters/data_mapper_adapter_spec.rb @@ -65,7 +65,6 @@ if ENV["MODEL_ADAPTER"] == "data_mapper" end it "should fetch only the articles that are published and not secret" do - pending "the `cannot` may require some custom SQL, maybe abstract out from Active Record adapter" @ability.can :read, Article, :published => true @ability.cannot :read, Article, :secret => true article1 = Article.create(:published => true, :secret => false) From 16bdb8d42eb03ff435bdadaff70c5307064304c2 Mon Sep 17 00:00:00 2001 From: Emmanuel Gomez Date: Fri, 29 Apr 2011 12:03:13 -0700 Subject: [PATCH 3/3] Return empty set early if no can rules are present. Thanks dkubb! --- lib/cancan/model_adapters/data_mapper_adapter.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/cancan/model_adapters/data_mapper_adapter.rb b/lib/cancan/model_adapters/data_mapper_adapter.rb index 9060b97..88058db 100644 --- a/lib/cancan/model_adapters/data_mapper_adapter.rb +++ b/lib/cancan/model_adapters/data_mapper_adapter.rb @@ -17,6 +17,7 @@ module CanCan def database_records scope = @model_class.all(:conditions => ["0 = 1"]) cans, cannots = @rules.partition { |r| r.base_behavior } + return scope if cans.empty? # apply unions first, then differences. this mean cannot overrides can cans.each { |r| scope += @model_class.all(:conditions => r.conditions) } cannots.each { |r| scope -= @model_class.all(:conditions => r.conditions) }