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"
|
when "mongoid"
|
||||||
gem "bson_ext", "~> 1.1"
|
gem "bson_ext", "~> 1.1"
|
||||||
gem "mongoid", "~> 2.0.0.beta.19"
|
gem "mongoid", "~> 2.0.0.beta.19"
|
||||||
|
else
|
||||||
|
raise "Unknown model adapter: #{ENV["MODEL_ADAPTER"]}"
|
||||||
end
|
end
|
||||||
|
|
||||||
gemspec
|
gemspec
|
||||||
|
|
|
@ -7,6 +7,7 @@ require 'cancan/query'
|
||||||
require 'cancan/inherited_resource'
|
require 'cancan/inherited_resource'
|
||||||
|
|
||||||
require 'cancan/model_adapters/abstract_adapter'
|
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/active_record_adapter' if defined? ActiveRecord
|
||||||
require 'cancan/model_adapters/data_mapper_adapter' if defined? DataMapper
|
require 'cancan/model_adapters/data_mapper_adapter' if defined? DataMapper
|
||||||
require 'cancan/model_adapters/mongoid_adapter' if defined? Mongoid
|
require 'cancan/model_adapters/mongoid_adapter' if defined? Mongoid
|
||||||
|
|
|
@ -187,7 +187,8 @@ module CanCan
|
||||||
end
|
end
|
||||||
|
|
||||||
def model_adapter(model_class, action)
|
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
|
end
|
||||||
|
|
||||||
# See ControllerAdditions#authorize! for documentation.
|
# See ControllerAdditions#authorize! for documentation.
|
||||||
|
|
|
@ -1,6 +1,20 @@
|
||||||
module CanCan
|
module CanCan
|
||||||
module ModelAdapters
|
module ModelAdapters
|
||||||
class AbstractAdapter
|
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)
|
def initialize(model_class, rules)
|
||||||
@model_class = model_class
|
@model_class = model_class
|
||||||
@rules = rules
|
@rules = rules
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
module CanCan
|
module CanCan
|
||||||
module ModelAdapters
|
module ModelAdapters
|
||||||
class ActiveRecordAdapter < AbstractAdapter
|
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
|
# 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.
|
# 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
|
||||||
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
|
describe "unauthorized message" do
|
||||||
after(:each) do
|
after(:each) do
|
||||||
I18n.backend = nil
|
I18n.backend = nil
|
||||||
|
|
|
@ -33,6 +33,12 @@ if ENV["MODEL_ADAPTER"].nil? || ENV["MODEL_ADAPTER"] == "active_record"
|
||||||
@comment_table = Comment.table_name
|
@comment_table = Comment.table_name
|
||||||
end
|
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
|
it "should not fetch any records when no abilities are defined" do
|
||||||
Article.create!
|
Article.create!
|
||||||
Article.accessible_by(@ability).should be_empty
|
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…
Reference in New Issue
Block a user