dynamically detect which model adapter to use given a class
This commit is contained in:
		
							parent
							
								
									cc30e838c0
								
							
						
					
					
						commit
						bbb02f7c8f
					
				
							
								
								
									
										2
									
								
								Gemfile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Gemfile
									
									
									
									
									
								
							@ -10,6 +10,8 @@ when "data_mapper"
 | 
			
		||||
when "mongoid"
 | 
			
		||||
  gem "bson_ext", "~> 1.1"
 | 
			
		||||
  gem "mongoid", "~> 2.0.0.beta.19"
 | 
			
		||||
else
 | 
			
		||||
  raise "Unknown model adapter: #{ENV["MODEL_ADAPTER"]}"
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
gemspec
 | 
			
		||||
 | 
			
		||||
@ -7,6 +7,7 @@ require 'cancan/query'
 | 
			
		||||
require 'cancan/inherited_resource'
 | 
			
		||||
 | 
			
		||||
require 'cancan/model_adapters/abstract_adapter'
 | 
			
		||||
require 'cancan/model_adapters/default_adapter'
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
@ -187,7 +187,8 @@ module CanCan
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def model_adapter(model_class, action)
 | 
			
		||||
      ModelAdapters::ActiveRecordAdapter.new(model_class, relevant_rules_for_query(action, model_class))
 | 
			
		||||
      adapter_class = ModelAdapters::AbstractAdapter.adapter_class(model_class)
 | 
			
		||||
      adapter_class.new(model_class, relevant_rules_for_query(action, model_class))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # See ControllerAdditions#authorize! for documentation.
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,20 @@
 | 
			
		||||
module CanCan
 | 
			
		||||
  module ModelAdapters
 | 
			
		||||
    class AbstractAdapter
 | 
			
		||||
      def self.inherited(subclass)
 | 
			
		||||
        @subclasses ||= []
 | 
			
		||||
        @subclasses << subclass
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def self.adapter_class(model_class)
 | 
			
		||||
        @subclasses.detect { |subclass| subclass.for_class?(model_class) } || DefaultAdapter
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Used to determine if the given adapter should be used for the passed in class.
 | 
			
		||||
      def self.for_class?(member_class)
 | 
			
		||||
        false # override in subclass
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def initialize(model_class, rules)
 | 
			
		||||
        @model_class = model_class
 | 
			
		||||
        @rules = rules
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,10 @@
 | 
			
		||||
module CanCan
 | 
			
		||||
  module ModelAdapters
 | 
			
		||||
    class ActiveRecordAdapter < AbstractAdapter
 | 
			
		||||
      def self.for_class?(model_class)
 | 
			
		||||
        model_class <= ActiveRecord::Base
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Returns conditions intended to be used inside a database query. Normally you will not call this
 | 
			
		||||
      # method directly, but instead go through ActiveRecordAdditions#accessible_by.
 | 
			
		||||
      #
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										7
									
								
								lib/cancan/model_adapters/default_adapter.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								lib/cancan/model_adapters/default_adapter.rb
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
			
		||||
module CanCan
 | 
			
		||||
  module ModelAdapters
 | 
			
		||||
    class DefaultAdapter < AbstractAdapter
 | 
			
		||||
      # This adapter is used when no matching adapter is found
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
@ -343,6 +343,14 @@ describe CanCan::Ability do
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "should determine model adapter class by asking AbstractAdapter" do
 | 
			
		||||
    model_class = Object.new
 | 
			
		||||
    adapter_class = Object.new
 | 
			
		||||
    stub(CanCan::ModelAdapters::AbstractAdapter).adapter_class(model_class) { adapter_class }
 | 
			
		||||
    stub(adapter_class).new(model_class, []) { :adapter_instance }
 | 
			
		||||
    @ability.model_adapter(model_class, :read).should == :adapter_instance
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe "unauthorized message" do
 | 
			
		||||
    after(:each) do
 | 
			
		||||
      I18n.backend = nil
 | 
			
		||||
 | 
			
		||||
@ -33,6 +33,12 @@ if ENV["MODEL_ADAPTER"].nil? || ENV["MODEL_ADAPTER"] == "active_record"
 | 
			
		||||
      @comment_table = Comment.table_name
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "should be for only active record classes" do
 | 
			
		||||
      CanCan::ModelAdapters::ActiveRecordAdapter.should_not be_for_class(Object)
 | 
			
		||||
      CanCan::ModelAdapters::ActiveRecordAdapter.should be_for_class(Article)
 | 
			
		||||
      CanCan::ModelAdapters::AbstractAdapter.adapter_class(Article).should == CanCan::ModelAdapters::ActiveRecordAdapter
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it "should not fetch any records when no abilities are defined" do
 | 
			
		||||
      Article.create!
 | 
			
		||||
      Article.accessible_by(@ability).should be_empty
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										7
									
								
								spec/cancan/model_adapters/default_adapter_spec.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								spec/cancan/model_adapters/default_adapter_spec.rb
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
			
		||||
require "spec_helper"
 | 
			
		||||
 | 
			
		||||
describe CanCan::ModelAdapters::DefaultAdapter do
 | 
			
		||||
  it "should be default for generic classes" do
 | 
			
		||||
    CanCan::ModelAdapters::AbstractAdapter.adapter_class(Object).should == CanCan::ModelAdapters::DefaultAdapter
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user