Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Add MongoMapper support #671

Open
wants to merge 1 commit into from

4 participants

@maxprokopiev

From: #649
Squashed in one commit

@andhapp
Collaborator

@juggler: Thanks. Will get this merged into 2.0 branch.

@maxprokopiev

any updates here? =)

@diegodorado

will this adapter be merged?

@diegodorado

@juggler : ok. thanks

@xhoy

Thanks for your submission! The ryanb/cancan repository has been inactive since Sep 06, 2013.
Since only Ryan himself has commit permissions, the CanCan project is on a standstill.

CanCan has many open issues, including missing support for Rails 4. To keep CanCan alive, an active fork exists at cancancommunity/cancancan. The new gem is cancancan. More info is available at #994.

If your pull request or issue is still applicable, it would be really appreciated if you resubmit it to CanCanCan.

We hope to see you on the other side!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jun 30, 2012
  1. @maxprokopiev

    Add MongoMapper support

    maxprokopiev authored
This page is out of date. Refresh to see the latest.
View
2  Rakefile
@@ -9,7 +9,7 @@ end
desc "Run specs for all adapters"
task :spec_all do
- %w[active_record data_mapper mongoid].each do |model_adapter|
+ %w[active_record data_mapper mongoid mongo_mapper].each do |model_adapter|
puts "MODEL_ADAPTER = #{model_adapter}"
system "rake spec MODEL_ADAPTER=#{model_adapter}"
end
View
2  cancan.gemspec
@@ -21,6 +21,8 @@ Gem::Specification.new do |s|
s.add_development_dependency "mongoid", "~> 2.4.8"
s.add_development_dependency "bson_ext", "~> 1.6.2"
+ s.add_development_dependency "mongo_mapper", "~> 0.11.1"
+
s.rubyforge_project = s.name
s.required_rubygems_version = ">= 1.3.4"
end
View
1  lib/cancan.rb
@@ -11,3 +11,4 @@
require 'cancan/model_adapters/active_record_adapter' if defined? ActiveRecord
require 'cancan/model_adapters/data_mapper_adapter' if defined? DataMapper
require 'cancan/model_adapters/mongoid_adapter' if defined?(Mongoid) && defined?(Mongoid::Document)
+require 'cancan/model_adapters/mongo_mapper_adapter' if defined?(MongoMapper) && defined?(MongoMapper::Document)
View
51 lib/cancan/model_adapters/mongo_mapper_adapter.rb
@@ -0,0 +1,51 @@
+module CanCan
+ module ModelAdapters
+ class MongoMapperAdapter < AbstractAdapter
+ def self.for_class?(model_class)
+ model_class <= MongoMapper::Document
+ end
+
+ def self.override_conditions_hash_matching?(subject, conditions)
+ conditions.any? do |k,v|
+ key_is_not_symbol = lambda { !k.kind_of?(Symbol) }
+ subject_value_is_array = lambda do
+ subject.respond_to?(k) && subject.send(k).is_a?(Array)
+ end
+
+ key_is_not_symbol.call || subject_value_is_array.call
+ end
+ end
+
+ def self.matches_conditions_hash?(subject, conditions)
+ subject.class.where(conditions).include? subject
+ end
+
+ def database_records
+ if @rules.size == 0
+ @model_class.where(:_id => {:$exists => false, :$type => 7}) # return no records
+ elsif @rules.size == 1
+ @model_class.where(@rules[0].conditions)
+ else
+ # we only need to process can rules if
+ # there are no rules with empty conditions
+ rules = @rules.reject { |rule| rule.conditions.empty? }
+ process_can_rules = @rules.count == rules.count
+ rules.inject(@model_class.where) do |records, rule|
+ if process_can_rules && rule.base_behavior
+ records.where rule.conditions
+ elsif !rule.base_behavior
+ records.remove rule.conditions
+ records
+ else
+ records
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+module MongoMapper::Document::ClassMethods
+ include CanCan::ModelAdditions::ClassMethods
+end
View
108 spec/cancan/model_adapters/mongo_mapper_adapter_spec.rb
@@ -0,0 +1,108 @@
+if ENV["MODEL_ADAPTER"] == "mongo_mapper"
+ require "spec_helper"
+
+ MongoMapper.connection = Mongo::Connection.new('localhost', 27017)
+ MongoMapper.database = "cancan_mongomapper_spec"
+
+ class MongoMapperProject
+ include MongoMapper::Document
+ end
+
+ describe CanCan::ModelAdapters::MongoMapperAdapter do
+ context "MongoMapper defined" do
+ before(:each) do
+ @ability = Object.new
+ @ability.extend(CanCan::Ability)
+ end
+
+ after(:each) do
+ MongoMapperProject.destroy_all
+ end
+
+ it "is for only MongoMapper classes" do
+ CanCan::ModelAdapters::MongoMapperAdapter.should_not be_for_class(Object)
+ CanCan::ModelAdapters::MongoMapperAdapter.should be_for_class(MongoMapperProject)
+ CanCan::ModelAdapters::AbstractAdapter.adapter_class(MongoMapperProject).should == CanCan::ModelAdapters::MongoMapperAdapter
+ end
+
+ it "finds record" do
+ project = MongoMapperProject.create
+ CanCan::ModelAdapters::MongoMapperAdapter.find(MongoMapperProject, project.id).should == project
+ end
+
+ it "compares properties on mongomapper documents with the conditions hash" do
+ model = MongoMapperProject.new
+ @ability.can :read, :mongo_mapper_projects, :id => model.id
+ @ability.should be_able_to(:read, model)
+ end
+
+ it "is able to read hashes when field is array" do
+ one_to_three = MongoMapperProject.create(:numbers => ['one', 'two', 'three'])
+ two_to_five = MongoMapperProject.create(:numbers => ['two', 'three', 'four', 'five'])
+
+ @ability.can :foo, :mongo_mapper_projects, :numbers => 'one'
+ @ability.should be_able_to(:foo, one_to_three)
+ @ability.should_not be_able_to(:foo, two_to_five)
+ end
+
+ it "returns [] when no ability is defined so no records are found" do
+ MongoMapperProject.create
+ MongoMapperProject.create
+ MongoMapperProject.create
+
+ MongoMapperProject.accessible_by(@ability, :read).entries.should == []
+ end
+
+ it "returns the correct records based on the defined ability" do
+ @ability.can :read, :mongo_mapper_projects, :title => "Sir"
+ sir = MongoMapperProject.create(:title => 'Sir')
+ lord = MongoMapperProject.create(:title => 'Lord')
+ dude = MongoMapperProject.create(:title => 'Dude')
+
+ MongoMapperProject.accessible_by(@ability, :read).entries.should == [sir]
+ end
+
+ it "is able to mix empty conditions and hashes" do
+ @ability.can :read, :mongo_mapper_projects, :title => 'Sir'
+ @ability.can :read, :mongo_mapper_projects
+ sir = MongoMapperProject.create(:title => 'Sir')
+ lord = MongoMapperProject.create(:title => 'Lord')
+
+ MongoMapperProject.accessible_by(@ability, :read).count.should == 2
+ end
+
+ it "returns everything when the defined ability is access all" do
+ @ability.can :access, :all
+ sir = MongoMapperProject.create(:title => 'Sir')
+ lord = MongoMapperProject.create(:title => 'Lord')
+ dude = MongoMapperProject.create(:title => 'Dude')
+
+ MongoMapperProject.accessible_by(@ability, :read).entries.should == [sir, lord, dude]
+ end
+
+ it "calls where with matching ability conditions" do
+ obj = MongoMapperProject.create(:foo => {:bar => 1})
+ @ability.can :read, :mongo_mapper_projects, :foo => {:bar => 1}
+ MongoMapperProject.accessible_by(@ability, :read).entries.first.should == obj
+ end
+
+ it "excludes from the result if set to cannot" do
+ obj = MongoMapperProject.create(:bar => 1)
+ obj2 = MongoMapperProject.create(:bar => 2)
+ @ability.can :read, :mongo_mapper_projects
+ @ability.cannot :read, :mongo_mapper_projects, :bar => 2
+ MongoMapperProject.accessible_by(@ability, :read).entries.should == [obj]
+ end
+
+ it "combines the rules" do
+ obj = MongoMapperProject.create(:bar => 1)
+ obj2 = MongoMapperProject.create(:bar => 2)
+ obj3 = MongoMapperProject.create(:bar => 3)
+ @ability.can :read, :mongo_mapper_projects, :bar => 1
+ @ability.can :read, :mongo_mapper_projects, :bar => 2
+ MongoMapperProject.accessible_by(@ability, :read).entries.should =~ [obj, obj2]
+ end
+
+ end
+ end
+end
View
2  spec/spec_helper.rb
@@ -11,6 +11,8 @@
require "dm-migrations"
when "mongoid"
require "mongoid"
+when "mongo_mapper"
+ require "mongo_mapper"
end
require 'active_support/all'
Something went wrong with that request. Please try again.