merging 1.6 additions into 2.0 branch

This commit is contained in:
Ryan Bates 2011-09-28 11:39:26 -07:00
commit 86063e4846
15 changed files with 101 additions and 19 deletions

9
.travis.yml Normal file
View File

@ -0,0 +1,9 @@
rvm:
- 1.8.7
- jruby
- ree
- rbx-2.0
notifications:
recipients:
- graf.otodrakula@gmail.com
- ryan@railscasts.com

View File

@ -3,7 +3,7 @@ source "http://rubygems.org"
case ENV["MODEL_ADAPTER"] case ENV["MODEL_ADAPTER"]
when nil, "active_record" when nil, "active_record"
gem "sqlite3" gem "sqlite3"
gem "activerecord", :require => "active_record" gem "activerecord", '~> 3.0.9', :require => "active_record"
gem "with_model" gem "with_model"
gem "meta_where" gem "meta_where"
when "data_mapper" when "data_mapper"

View File

@ -11,7 +11,7 @@ Gem::Specification.new do |s|
s.require_path = "lib" s.require_path = "lib"
s.add_development_dependency 'rspec', '~> 2.1.0' s.add_development_dependency 'rspec', '~> 2.1.0'
s.add_development_dependency 'rails', '~> 3.0.0' s.add_development_dependency 'rails', '~> 3.0.9'
s.add_development_dependency 'rr', '~> 0.10.11' # 1.0.0 has respond_to? issues: http://github.com/btakita/rr/issues/issue/43 s.add_development_dependency 'rr', '~> 0.10.11' # 1.0.0 has respond_to? issues: http://github.com/btakita/rr/issues/issue/43
s.add_development_dependency 'supermodel', '~> 0.1.4' s.add_development_dependency 'supermodel', '~> 0.1.4'

View File

@ -188,7 +188,7 @@ module CanCan
skip_authorize_resource(*args) skip_authorize_resource(*args)
end end
# Skip both the loading behavior of CanCan. This is useful when using +load_and_authorize_resource+ but want to # Skip the loading behavior of CanCan. This is useful when using +load_and_authorize_resource+ but want to
# only do authorization on certain actions. You can pass :only and :except options to specify which actions to # only do authorization on certain actions. You can pass :only and :except options to specify which actions to
# skip the effects on. It will apply to all actions by default. # skip the effects on. It will apply to all actions by default.
# #
@ -205,7 +205,7 @@ module CanCan
cancan_skipper[:load][name] = options cancan_skipper[:load][name] = options
end end
# Skip both the authorization behavior of CanCan. This is useful when using +load_and_authorize_resource+ but want to # Skip the authorization behavior of CanCan. This is useful when using +load_and_authorize_resource+ but want to
# only do loading on certain actions. You can pass :only and :except options to specify which actions to # only do loading on certain actions. You can pass :only and :except options to specify which actions to
# skip the effects on. It will apply to all actions by default. # skip the effects on. It will apply to all actions by default.
# #

View File

@ -107,10 +107,22 @@ module CanCan
if @options[:singleton] && parent_resource.respond_to?(name) if @options[:singleton] && parent_resource.respond_to?(name)
parent_resource.send(name) parent_resource.send(name)
else else
@options[:find_by] ? resource_base.send("find_by_#{@options[:find_by]}!", id_param) : resource_base.find(id_param) if @options[:find_by]
if resource_base.respond_to? "find_by_#{@options[:find_by]}!"
resource_base.send("find_by_#{@options[:find_by]}!", id_param)
else
resource_base.send(@options[:find_by], id_param)
end
else
adapter.find(resource_base, id_param)
end
end end
end end
def adapter
ModelAdapters::AbstractAdapter.adapter_class(resource_class)
end
def authorization_action def authorization_action
parent? ? :show : @params[:action].to_sym parent? ? :show : @params[:action].to_sym
end end

View File

@ -43,7 +43,7 @@ module CanCan
@message = message @message = message
@action = action @action = action
@subject = subject @subject = subject
@default_message = "You are not authorized to access this page." @default_message = I18n.t(:"unauthorized.default", :default => "You are not authorized to access this page.")
end end
def to_s def to_s

View File

@ -1,5 +1,5 @@
RSpec = Spec unless defined? RSpec # for RSpec 1 compatability rspec_module = defined?(RSpec::Core) ? 'RSpec' : 'Spec' # for RSpec 1 compatability
RSpec::Matchers.define :be_able_to do |*args| Kernel.const_get(rspec_module)::Matchers.define :be_able_to do |*args|
match do |ability| match do |ability|
ability.can?(*args) ability.can?(*args)
end end

View File

@ -15,6 +15,11 @@ module CanCan
false # override in subclass false # override in subclass
end end
# Override if you need custom find behavior
def self.find(model_class, id)
model_class.find(id)
end
# Used to determine if this model adapter will override the matching behavior for a hash of conditions. # Used to determine if this model adapter will override the matching behavior for a hash of conditions.
# If this returns true then matches_conditions_hash? will be called. See Rule#matches_conditions_hash # If this returns true then matches_conditions_hash? will be called. See Rule#matches_conditions_hash
def self.override_conditions_hash_matching?(subject, conditions) def self.override_conditions_hash_matching?(subject, conditions)

View File

@ -5,6 +5,10 @@ module CanCan
model_class <= DataMapper::Resource model_class <= DataMapper::Resource
end end
def self.find(model_class, id)
model_class.get(id)
end
def self.override_conditions_hash_matching?(subject, conditions) def self.override_conditions_hash_matching?(subject, conditions)
conditions.any? { |k,v| !k.kind_of?(Symbol) } conditions.any? { |k,v| !k.kind_of?(Symbol) }
end end
@ -27,6 +31,4 @@ module CanCan
end # module ModelAdapters end # module ModelAdapters
end # module CanCan end # module CanCan
DataMapper::Model.class_eval do DataMapper::Model.append_extensions(CanCan::ModelAdditions::ClassMethods)
include CanCan::ModelAdditions::ClassMethods
end

View File

@ -329,6 +329,14 @@ describe CanCan::ControllerResource do
CanCan::ControllerResource.new(@controller, :authorize => true).process CanCan::ControllerResource.new(@controller, :authorize => true).process
end end
it "should allow full find method to be passed into find_by option" do
project = Project.create!(:name => "foo")
@params.merge!(:action => "show", :id => "foo")
resource = CanCan::ControllerResource.new(@controller, :find_by => :find_by_name, :load => true)
resource.process
@controller.instance_variable_get(:@project).should == project
end
it "should authorize each new attribute in the update action" do it "should authorize each new attribute in the update action" do
@params.merge!(:action => "update", :id => 123, :project => {:name => "foo"}) @params.merge!(:action => "update", :id => 123, :project => {:name => "foo"})
@controller.instance_variable_set(:@project, :some_project) @controller.instance_variable_set(:@project, :some_project)
@ -349,13 +357,13 @@ describe CanCan::ControllerResource do
# CanCan::ControllerResource.new(@controller, :name => :foo) # CanCan::ControllerResource.new(@controller, :name => :foo)
# }.should raise_error(CanCan::ImplementationRemoved) # }.should raise_error(CanCan::ImplementationRemoved)
# end # end
# #
# it "should raise ImplementationRemoved exception when specifying :resource option since it is no longer used" do # it "should raise ImplementationRemoved exception when specifying :resource option since it is no longer used" do
# lambda { # lambda {
# CanCan::ControllerResource.new(@controller, :resource => Project) # CanCan::ControllerResource.new(@controller, :resource => Project)
# }.should raise_error(CanCan::ImplementationRemoved) # }.should raise_error(CanCan::ImplementationRemoved)
# end # end
# #
# it "should raise ImplementationRemoved exception when passing :nested option" do # it "should raise ImplementationRemoved exception when passing :nested option" do
# lambda { # lambda {
# CanCan::ControllerResource.new(@controller, :nested => :project) # CanCan::ControllerResource.new(@controller, :nested => :project)
@ -372,7 +380,7 @@ describe CanCan::ControllerResource do
# @params.merge!(:action => "other_action") # @params.merge!(:action => "other_action")
# CanCan::ControllerResource.new(@controller).skip?(:load).should be_false # CanCan::ControllerResource.new(@controller).skip?(:load).should be_false
# end # end
# #
# it "should skip resource behavior for :only one action on resource" do # it "should skip resource behavior for :only one action on resource" do
# stub(@controller_class).cancan_skipper { {:authorize => {:project => {:only => :index}}} } # stub(@controller_class).cancan_skipper { {:authorize => {:project => {:only => :index}}} }
# @params.merge!(:action => "index") # @params.merge!(:action => "index")
@ -381,7 +389,7 @@ describe CanCan::ControllerResource do
# @params.merge!(:action => "other_action") # @params.merge!(:action => "other_action")
# CanCan::ControllerResource.new(@controller, :project).skip?(:authorize).should be_false # CanCan::ControllerResource.new(@controller, :project).skip?(:authorize).should be_false
# end # end
# #
# it "should skip resource behavior :except actions in array" do # it "should skip resource behavior :except actions in array" do
# stub(@controller_class).cancan_skipper { {:load => {nil => {:except => [:index, :show]}}} } # stub(@controller_class).cancan_skipper { {:load => {nil => {:except => [:index, :show]}}} }
# @params.merge!(:action => "index") # @params.merge!(:action => "index")
@ -392,7 +400,7 @@ describe CanCan::ControllerResource do
# CanCan::ControllerResource.new(@controller).skip?(:load).should be_true # CanCan::ControllerResource.new(@controller).skip?(:load).should be_true
# CanCan::ControllerResource.new(@controller, :some_resource).skip?(:load).should be_false # CanCan::ControllerResource.new(@controller, :some_resource).skip?(:load).should be_false
# end # end
# #
# it "should skip resource behavior :except one action on resource" do # it "should skip resource behavior :except one action on resource" do
# stub(@controller_class).cancan_skipper { {:authorize => {:project => {:except => :index}}} } # stub(@controller_class).cancan_skipper { {:authorize => {:project => {:except => :index}}} }
# @params.merge!(:action => "index") # @params.merge!(:action => "index")
@ -401,7 +409,7 @@ describe CanCan::ControllerResource do
# CanCan::ControllerResource.new(@controller).skip?(:authorize).should be_false # CanCan::ControllerResource.new(@controller).skip?(:authorize).should be_false
# CanCan::ControllerResource.new(@controller, :project).skip?(:authorize).should be_true # CanCan::ControllerResource.new(@controller, :project).skip?(:authorize).should be_true
# end # end
# #
# it "should skip loading and authorization" do # it "should skip loading and authorization" do
# stub(@controller_class).cancan_skipper { {:authorize => {nil => {}}, :load => {nil => {}}} } # stub(@controller_class).cancan_skipper { {:authorize => {nil => {}}, :load => {nil => {}}} }
# @params.merge!(:action => "new") # @params.merge!(:action => "new")

View File

@ -32,4 +32,27 @@ describe CanCan::Unauthorized do
@exception.message.should == "Access denied!" @exception.message.should == "Access denied!"
end end
end end
describe "i18n in the default message" do
after(:each) do
I18n.backend = nil
end
it "uses i18n for the default message" do
I18n.backend.store_translations :en, :unauthorized => {:default => "This is a different message"}
@exception = CanCan::Unauthorized.new
@exception.message.should == "This is a different message"
end
it "defaults to a nice message" do
@exception = CanCan::Unauthorized.new
@exception.message.should == "You are not authorized to access this page."
end
it "does not use translation if a message is given" do
@exception = CanCan::Unauthorized.new("Hey! You're not welcome here")
@exception.message.should == "Hey! You're not welcome here"
@exception.message.should_not == "You are not authorized to access this page."
end
end
end end

View File

@ -56,6 +56,11 @@ if ENV["MODEL_ADAPTER"].nil? || ENV["MODEL_ADAPTER"] == "active_record"
CanCan::ModelAdapters::AbstractAdapter.adapter_class(Article).should == CanCan::ModelAdapters::ActiveRecordAdapter CanCan::ModelAdapters::AbstractAdapter.adapter_class(Article).should == CanCan::ModelAdapters::ActiveRecordAdapter
end end
it "should find record" do
article = Article.create!
CanCan::ModelAdapters::ActiveRecordAdapter.find(Article, article.id).should == article
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

View File

@ -36,6 +36,11 @@ if ENV["MODEL_ADAPTER"] == "data_mapper"
CanCan::ModelAdapters::AbstractAdapter.adapter_class(Article).should == CanCan::ModelAdapters::DataMapperAdapter CanCan::ModelAdapters::AbstractAdapter.adapter_class(Article).should == CanCan::ModelAdapters::DataMapperAdapter
end end
it "should find record" do
article = Article.create
CanCan::ModelAdapters::DataMapperAdapter.find(Article, article.id).should == article
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

View File

@ -36,6 +36,11 @@ if ENV["MODEL_ADAPTER"] == "mongoid"
CanCan::ModelAdapters::AbstractAdapter.adapter_class(MongoidProject).should == CanCan::ModelAdapters::MongoidAdapter CanCan::ModelAdapters::AbstractAdapter.adapter_class(MongoidProject).should == CanCan::ModelAdapters::MongoidAdapter
end end
it "should find record" do
project = MongoidProject.create
CanCan::ModelAdapters::MongoidAdapter.find(MongoidProject, project.id).should == project
end
it "should compare properties on mongoid documents with the conditions hash" do it "should compare properties on mongoid documents with the conditions hash" do
model = MongoidProject.new model = MongoidProject.new
@ability.can :read, :mongoid_projects, :id => model.id @ability.can :read, :mongoid_projects, :id => model.id
@ -180,7 +185,7 @@ if ENV["MODEL_ADAPTER"] == "mongoid"
@ability.can :read, :mongoid_projects, :foo => {:bar => 1} @ability.can :read, :mongoid_projects, :foo => {:bar => 1}
MongoidProject.accessible_by(@ability, :read).entries.first.should == obj MongoidProject.accessible_by(@ability, :read).entries.first.should == obj
end end
it "should exclude from the result if set to cannot" do it "should exclude from the result if set to cannot" do
obj = MongoidProject.create(:bar => 1) obj = MongoidProject.create(:bar => 1)
obj2 = MongoidProject.create(:bar => 2) obj2 = MongoidProject.create(:bar => 2)
@ -197,7 +202,7 @@ if ENV["MODEL_ADAPTER"] == "mongoid"
@ability.can :read, :mongoid_projects, :bar => 2 @ability.can :read, :mongoid_projects, :bar => 2
MongoidProject.accessible_by(@ability, :read).entries.should =~ [obj, obj2] MongoidProject.accessible_by(@ability, :read).entries.should =~ [obj, obj2]
end end
it "should not allow to fetch records when ability with just block present" do it "should not allow to fetch records when ability with just block present" do
@ability.can :read, :mongoid_projects do @ability.can :read, :mongoid_projects do
false false

View File

@ -30,4 +30,12 @@ end
class Project < SuperModel::Base class Project < SuperModel::Base
belongs_to :category belongs_to :category
attr_accessor :category # why doesn't SuperModel do this automatically? attr_accessor :category # why doesn't SuperModel do this automatically?
def self.respond_to?(method, include_private = false)
if method.to_s == "find_by_name!" # hack to simulate ActiveRecord
true
else
super
end
end
end end