getting all specs passing again

This commit is contained in:
Ryan Bates 2011-03-23 19:47:34 -07:00
parent 98ed39264e
commit 3a825ed0d1
10 changed files with 92 additions and 86 deletions

1
.rspec
View File

@ -1 +1,2 @@
--color
--backtrace

View File

@ -207,7 +207,7 @@ module CanCan
def model_adapter(model_class, action)
adapter_class = ModelAdapters::AbstractAdapter.adapter_class(model_class)
adapter_class.new(model_class, relevant_rules_for_query(action, model_class))
adapter_class.new(model_class, relevant_rules_for_query(action, model_class.to_s.underscore.pluralize.to_sym))
end
# See ControllerAdditions#authorize! for documentation.
@ -249,7 +249,7 @@ module CanCan
private
def unauthorized_message_keys(action, subject)
subject = (subject.kind_of?(Symbol) ? subject.to_s : subject.class.to_s.underscore.humanize.downcase.pluralize)
subject = (subject.kind_of?(Symbol) ? subject.to_s : subject.class.to_s.underscore.pluralize)
[aliases_for(:subjects, subject.to_sym), :all].flatten.map do |try_subject|
[aliases_for(:actions, action.to_sym), :access].flatten.map do |try_action|
:"#{try_action}.#{try_subject}"

View File

@ -38,7 +38,7 @@ module CanCan
def authorize_resource
unless skip?(:authorize)
@controller.authorize!(authorization_action, resource_instance || resource_class_with_parent)
@controller.authorize!(authorization_action, resource_instance || subject_name_with_parent)
end
end
@ -74,7 +74,7 @@ module CanCan
end
def load_collection?
resource_base.respond_to?(:accessible_by) && !current_ability.has_block?(authorization_action, resource_class)
resource_base.respond_to?(:accessible_by) && !current_ability.has_block?(authorization_action, subject_name)
end
def load_collection
@ -91,7 +91,7 @@ module CanCan
end
def initial_attributes
current_ability.attributes_for(@params[:action].to_sym, resource_class).delete_if do |key, value|
current_ability.attributes_for(@params[:action].to_sym, subject_name).delete_if do |key, value|
@params[name] && @params[name].include?(key)
end
end
@ -128,8 +128,12 @@ module CanCan
end
end
def resource_class_with_parent
parent_resource ? {parent_resource => resource_class} : resource_class
def subject_name
resource_class.to_s.underscore.pluralize.to_sym
end
def subject_name_with_parent
parent_resource ? {parent_resource => subject_name} : subject_name
end
def resource_instance=(instance)

View File

@ -20,7 +20,9 @@ module CanCan
@model_class.where(:_id => {'$exists' => false, '$type' => 7}) # return no records in Mongoid
else
@rules.inject(@model_class.all) do |records, rule|
if rule.base_behavior
if rule.conditions.empty?
records
elsif rule.base_behavior
records.or(rule.conditions)
else
records.excludes(rule.conditions)

View File

@ -139,7 +139,7 @@ module CanCan
end
def subject_name(subject)
subject.class.to_s.underscore.humanize.downcase.pluralize.to_sym
subject.class.to_s.underscore.pluralize.to_sym
end
def model_adapter(subject)

View File

@ -269,7 +269,7 @@ describe CanCan::Ability do
end
# Determining Conditions
# Determining Kind of Conditions
it "knows when a block is used for conditions" do
@ability.can :read, :books
@ -288,7 +288,6 @@ describe CanCan::Ability do
end
it "determines model adapter class by asking AbstractAdapter" do
pending
model_class = Object.new
adapter_class = Object.new
stub(CanCan::ModelAdapters::AbstractAdapter).adapter_class(model_class) { adapter_class }

View File

@ -52,7 +52,7 @@ describe CanCan::ControllerResource do
it "should build a new resource with attributes from current ability" do
@params.merge!(:action => "new")
@ability.can(:create, Project, :name => "from conditions")
@ability.can(:create, :projects, :name => "from conditions")
resource = CanCan::ControllerResource.new(@controller)
resource.load_resource
@controller.instance_variable_get(:@project).name.should == "from conditions"
@ -60,7 +60,7 @@ describe CanCan::ControllerResource do
it "should override initial attributes with params" do
@params.merge!(:action => "new", :project => {:name => "from params"})
@ability.can(:create, Project, :name => "from conditions")
@ability.can(:create, :projects, :name => "from conditions")
resource = CanCan::ControllerResource.new(@controller)
resource.load_resource
@controller.instance_variable_get(:@project).name.should == "from params"
@ -86,7 +86,7 @@ describe CanCan::ControllerResource do
it "should not use accessible_by when defining abilities through a block" do
stub(Project).accessible_by(@ability) { :found_projects }
@params[:action] = "index"
@ability.can(:read, Project) { |p| false }
@ability.can(:read, :projects) { |p| false }
resource = CanCan::ControllerResource.new(@controller)
resource.load_resource
@controller.instance_variable_get(:@project).should be_nil
@ -96,7 +96,7 @@ describe CanCan::ControllerResource do
it "should not authorize single resource in collection action" do
@params[:action] = "index"
@controller.instance_variable_set(:@project, :some_project)
stub(@controller).authorize!(:index, Project) { raise CanCan::AccessDenied }
stub(@controller).authorize!(:index, :projects) { raise CanCan::AccessDenied }
resource = CanCan::ControllerResource.new(@controller)
lambda { resource.authorize_resource }.should raise_error(CanCan::AccessDenied)
end
@ -119,7 +119,7 @@ describe CanCan::ControllerResource do
it "should perform authorization using controller action and non loaded model" do
@params.merge!(:action => "show", :id => 123)
stub(@controller).authorize!(:show, Project) { raise CanCan::AccessDenied }
stub(@controller).authorize!(:show, :projects) { raise CanCan::AccessDenied }
resource = CanCan::ControllerResource.new(@controller)
lambda { resource.authorize_resource }.should raise_error(CanCan::AccessDenied)
end
@ -243,7 +243,7 @@ describe CanCan::ControllerResource do
@params.merge!(:action => "index")
category = Object.new
@controller.instance_variable_set(:@category, category)
stub(@controller).authorize!(:index, category => Project) { raise CanCan::AccessDenied }
stub(@controller).authorize!(:index, category => :projects) { raise CanCan::AccessDenied }
resource = CanCan::ControllerResource.new(@controller, :through => :category)
lambda { resource.authorize_resource }.should raise_error(CanCan::AccessDenied)
end
@ -311,7 +311,7 @@ describe CanCan::ControllerResource do
it "should authorize based on resource name if class is false" do
@params.merge!(:action => "show", :id => 123)
stub(@controller).authorize!(:show, :project) { raise CanCan::AccessDenied }
stub(@controller).authorize!(:show, :projects) { raise CanCan::AccessDenied }
resource = CanCan::ControllerResource.new(@controller, :class => false)
lambda { resource.authorize_resource }.should raise_error(CanCan::AccessDenied)
end

View File

@ -62,21 +62,21 @@ if ENV["MODEL_ADAPTER"].nil? || ENV["MODEL_ADAPTER"] == "active_record"
end
it "should fetch all articles when one can read all" do
@ability.can :read, Article
@ability.can :read, :articles
article = Article.create!
Article.accessible_by(@ability).should == [article]
end
it "should fetch only the articles that are published" do
@ability.can :read, Article, :published => true
@ability.can :read, :articles, :published => true
article1 = Article.create!(:published => true)
article2 = Article.create!(:published => false)
Article.accessible_by(@ability).should == [article1]
end
it "should fetch any articles which are published or secret" do
@ability.can :read, Article, :published => true
@ability.can :read, Article, :secret => true
@ability.can :read, :articles, :published => true
@ability.can :read, :articles, :secret => true
article1 = Article.create!(:published => true, :secret => false)
article2 = Article.create!(:published => true, :secret => true)
article3 = Article.create!(:published => false, :secret => true)
@ -85,8 +85,8 @@ if ENV["MODEL_ADAPTER"].nil? || ENV["MODEL_ADAPTER"] == "active_record"
end
it "should fetch only the articles that are published and not secret" do
@ability.can :read, Article, :published => true
@ability.cannot :read, Article, :secret => true
@ability.can :read, :articles, :published => true
@ability.cannot :read, :articles, :secret => true
article1 = Article.create!(:published => true, :secret => false)
article2 = Article.create!(:published => true, :secret => true)
article3 = Article.create!(:published => false, :secret => true)
@ -95,22 +95,22 @@ if ENV["MODEL_ADAPTER"].nil? || ENV["MODEL_ADAPTER"] == "active_record"
end
it "should only read comments for articles which are published" do
@ability.can :read, Comment, :article => { :published => true }
@ability.can :read, :comments, :article => { :published => true }
comment1 = Comment.create!(:article => Article.create!(:published => true))
comment2 = Comment.create!(:article => Article.create!(:published => false))
Comment.accessible_by(@ability).should == [comment1]
end
it "should only read comments for visible categories through articles" do
@ability.can :read, Comment, :article => { :category => { :visible => true } }
@ability.can :read, :comments, :article => { :category => { :visible => true } }
comment1 = Comment.create!(:article => Article.create!(:category => Category.create!(:visible => true)))
comment2 = Comment.create!(:article => Article.create!(:category => Category.create!(:visible => false)))
Comment.accessible_by(@ability).should == [comment1]
end
it "should allow conditions in SQL and merge with hash conditions" do
@ability.can :read, Article, :published => true
@ability.can :read, Article, ["secret=?", true]
@ability.can :read, :articles, :published => true
@ability.can :read, :articles, ["secret=?", true]
article1 = Article.create!(:published => true, :secret => false)
article2 = Article.create!(:published => true, :secret => true)
article3 = Article.create!(:published => false, :secret => true)
@ -119,27 +119,27 @@ if ENV["MODEL_ADAPTER"].nil? || ENV["MODEL_ADAPTER"] == "active_record"
end
it "should allow a scope for conditions" do
@ability.can :read, Article, Article.where(:secret => true)
@ability.can :read, :articles, Article.where(:secret => true)
article1 = Article.create!(:secret => true)
article2 = Article.create!(:secret => false)
Article.accessible_by(@ability).should == [article1]
end
it "should raise an exception when trying to merge scope with other conditions" do
@ability.can :read, Article, :published => true
@ability.can :read, Article, Article.where(:secret => true)
lambda { Article.accessible_by(@ability) }.should raise_error(CanCan::Error, "Unable to merge an Active Record scope with other conditions. Instead use a hash or SQL for read Article ability.")
@ability.can :read, :articles, :published => true
@ability.can :read, :articles, Article.where(:secret => true)
lambda { Article.accessible_by(@ability) }.should raise_error(CanCan::Error, "Unable to merge an Active Record scope with other conditions. Instead use a hash or SQL for read articles ability.")
end
it "should not allow to fetch records when ability with just block present" do
@ability.can :read, Article do
@ability.can :read, :articles do
false
end
lambda { Article.accessible_by(@ability) }.should raise_error(CanCan::Error)
end
it "should not allow to check ability on object against SQL conditions without block" do
@ability.can :read, Article, ["secret=?", true]
@ability.can :read, :articles, ["secret=?", true]
lambda { @ability.can? :read, Article.new }.should raise_error(CanCan::Error)
end
@ -148,47 +148,47 @@ if ENV["MODEL_ADAPTER"].nil? || ENV["MODEL_ADAPTER"] == "active_record"
end
it "should return false conditions for cannot clause" do
@ability.cannot :read, Article
@ability.cannot :read, :articles
@ability.model_adapter(Article, :read).conditions.should == "'t'='f'"
end
it "should return SQL for single `can` definition in front of default `cannot` condition" do
@ability.cannot :read, Article
@ability.can :read, Article, :published => false, :secret => true
@ability.cannot :read, :articles
@ability.can :read, :articles, :published => false, :secret => true
@ability.model_adapter(Article, :read).conditions.should orderlessly_match(%Q["#{@article_table}"."published" = 'f' AND "#{@article_table}"."secret" = 't'])
end
it "should return true condition for single `can` definition in front of default `can` condition" do
@ability.can :read, Article
@ability.can :read, Article, :published => false, :secret => true
@ability.can :read, :articles
@ability.can :read, :articles, :published => false, :secret => true
@ability.model_adapter(Article, :read).conditions.should == "'t'='t'"
end
it "should return `false condition` for single `cannot` definition in front of default `cannot` condition" do
@ability.cannot :read, Article
@ability.cannot :read, Article, :published => false, :secret => true
@ability.cannot :read, :articles
@ability.cannot :read, :articles, :published => false, :secret => true
@ability.model_adapter(Article, :read).conditions.should == "'t'='f'"
end
it "should return `not (sql)` for single `cannot` definition in front of default `can` condition" do
@ability.can :read, Article
@ability.cannot :read, Article, :published => false, :secret => true
@ability.can :read, :articles
@ability.cannot :read, :articles, :published => false, :secret => true
@ability.model_adapter(Article, :read).conditions.should orderlessly_match(%Q["not (#{@article_table}"."published" = 'f' AND "#{@article_table}"."secret" = 't')])
end
it "should return appropriate sql conditions in complex case" do
@ability.can :read, Article
@ability.can :manage, Article, :id => 1
@ability.can :update, Article, :published => true
@ability.cannot :update, Article, :secret => true
@ability.can :read, :articles
@ability.can :access, :articles, :id => 1
@ability.can :update, :articles, :published => true
@ability.cannot :update, :articles, :secret => true
@ability.model_adapter(Article, :update).conditions.should == %Q[not ("#{@article_table}"."secret" = 't') AND (("#{@article_table}"."published" = 't') OR ("#{@article_table}"."id" = 1))]
@ability.model_adapter(Article, :manage).conditions.should == {:id => 1}
@ability.model_adapter(Article, :access).conditions.should == {:id => 1}
@ability.model_adapter(Article, :read).conditions.should == "'t'='t'"
end
it "should not forget conditions when calling with SQL string" do
@ability.can :read, Article, :published => true
@ability.can :read, Article, ['secret=?', false]
@ability.can :read, :articles, :published => true
@ability.can :read, :articles, ['secret=?', false]
adapter = @ability.model_adapter(Article, :read)
2.times do
adapter.conditions.should == %Q[(secret='f') OR ("#{@article_table}"."published" = 't')]
@ -200,25 +200,25 @@ if ENV["MODEL_ADAPTER"].nil? || ENV["MODEL_ADAPTER"] == "active_record"
end
it "should have nil joins if no nested hashes specified in conditions" do
@ability.can :read, Article, :published => false
@ability.can :read, Article, :secret => true
@ability.can :read, :articles, :published => false
@ability.can :read, :articles, :secret => true
@ability.model_adapter(Article, :read).joins.should be_nil
end
it "should merge separate joins into a single array" do
@ability.can :read, Article, :project => { :blocked => false }
@ability.can :read, Article, :company => { :admin => true }
@ability.can :read, :articles, :project => { :blocked => false }
@ability.can :read, :articles, :company => { :admin => true }
@ability.model_adapter(Article, :read).joins.inspect.should orderlessly_match([:company, :project].inspect)
end
it "should merge same joins into a single array" do
@ability.can :read, Article, :project => { :blocked => false }
@ability.can :read, Article, :project => { :admin => true }
@ability.can :read, :articles, :project => { :blocked => false }
@ability.can :read, :articles, :project => { :admin => true }
@ability.model_adapter(Article, :read).joins.should == [:project]
end
it "should restrict articles given a MetaWhere condition" do
@ability.can :read, Article, :priority.lt => 2
@ability.can :read, :articles, :priority.lt => 2
article1 = Article.create!(:priority => 1)
article2 = Article.create!(:priority => 3)
Article.accessible_by(@ability).should == [article1]

View File

@ -42,21 +42,21 @@ if ENV["MODEL_ADAPTER"] == "data_mapper"
end
it "should fetch all articles when one can read all" do
@ability.can :read, Article
@ability.can :read, :articles
article = Article.create
Article.accessible_by(@ability).should == [article]
end
it "should fetch only the articles that are published" do
@ability.can :read, Article, :published => true
@ability.can :read, :articles, :published => true
article1 = Article.create(:published => true)
article2 = Article.create(:published => false)
Article.accessible_by(@ability).should == [article1]
end
it "should fetch any articles which are published or secret" do
@ability.can :read, Article, :published => true
@ability.can :read, Article, :secret => true
@ability.can :read, :articles, :published => true
@ability.can :read, :articles, :secret => true
article1 = Article.create(:published => true, :secret => false)
article2 = Article.create(:published => true, :secret => true)
article3 = Article.create(:published => false, :secret => true)
@ -66,8 +66,8 @@ if ENV["MODEL_ADAPTER"] == "data_mapper"
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
@ability.can :read, :articles, :published => true
@ability.cannot :read, :articles, :secret => true
article1 = Article.create(:published => true, :secret => false)
article2 = Article.create(:published => true, :secret => true)
article3 = Article.create(:published => false, :secret => true)
@ -76,22 +76,22 @@ if ENV["MODEL_ADAPTER"] == "data_mapper"
end
it "should only read comments for articles which are published" do
@ability.can :read, Comment, :article => { :published => true }
@ability.can :read, :comments, :article => { :published => true }
comment1 = Comment.create(:article => Article.create!(:published => true))
comment2 = Comment.create(:article => Article.create!(:published => false))
Comment.accessible_by(@ability).should == [comment1]
end
it "should allow conditions in SQL and merge with hash conditions" do
@ability.can :read, Article, :published => true
@ability.can :read, Article, ["secret=?", true]
@ability.can :read, :articles, :published => true
@ability.can :read, :articles, ["secret=?", true]
article1 = Article.create(:published => true, :secret => false)
article4 = Article.create(:published => false, :secret => false)
Article.accessible_by(@ability).should == [article1]
end
it "should match gt comparison" do
@ability.can :read, Article, :priority.gt => 3
@ability.can :read, :articles, :priority.gt => 3
article1 = Article.create(:priority => 4)
article2 = Article.create(:priority => 3)
Article.accessible_by(@ability).should == [article1]
@ -100,7 +100,7 @@ if ENV["MODEL_ADAPTER"] == "data_mapper"
end
it "should match gte comparison" do
@ability.can :read, Article, :priority.gte => 3
@ability.can :read, :articles, :priority.gte => 3
article1 = Article.create(:priority => 4)
article2 = Article.create(:priority => 3)
article3 = Article.create(:priority => 2)

View File

@ -38,7 +38,7 @@ if ENV["MODEL_ADAPTER"] == "mongoid"
it "should compare properties on mongoid documents with the conditions hash" do
model = MongoidProject.new
@ability.can :read, MongoidProject, :id => model.id
@ability.can :read, :mongoid_projects, :id => model.id
@ability.should be_able_to(:read, model)
end
@ -51,7 +51,7 @@ if ENV["MODEL_ADAPTER"] == "mongoid"
end
it "should return the correct records based on the defined ability" do
@ability.can :read, MongoidProject, :title => "Sir"
@ability.can :read, :mongoid_projects, :title => "Sir"
sir = MongoidProject.create(:title => 'Sir')
lord = MongoidProject.create(:title => 'Lord')
dude = MongoidProject.create(:title => 'Dude')
@ -59,8 +59,8 @@ if ENV["MODEL_ADAPTER"] == "mongoid"
MongoidProject.accessible_by(@ability, :read).entries.should == [sir]
end
it "should return everything when the defined ability is manage all" do
@ability.can :manage, :all
it "should return everything when the defined ability is access all" do
@ability.can :access, :all
sir = MongoidProject.create(:title => 'Sir')
lord = MongoidProject.create(:title => 'Lord')
dude = MongoidProject.create(:title => 'Dude')
@ -72,7 +72,7 @@ if ENV["MODEL_ADAPTER"] == "mongoid"
describe "Mongoid::Criteria where clause Symbol extensions using MongoDB expressions" do
it "should handle :field.in" do
obj = MongoidProject.create(:title => 'Sir')
@ability.can :read, MongoidProject, :title.in => ["Sir", "Madam"]
@ability.can :read, :mongoid_projects, :title.in => ["Sir", "Madam"]
@ability.can?(:read, obj).should == true
MongoidProject.accessible_by(@ability, :read).should == [obj]
@ -85,20 +85,20 @@ if ENV["MODEL_ADAPTER"] == "mongoid"
obj = MongoidProject.create(:title => 'Bird')
@conditions = {:title.nin => ["Fork", "Spoon"]}
@ability.can :read, MongoidProject, @conditions
@ability.can :read, :mongoid_projects, @conditions
@ability.should be_able_to(:read, obj)
end
it "Calls the base version if there are no mongoid criteria" do
obj = MongoidProject.new(:title => 'Bird')
@conditions = {:id => obj.id}
@ability.can :read, MongoidProject, @conditions
@ability.can :read, :mongoid_projects, @conditions
@ability.should be_able_to(:read, obj)
end
end
it "should handle :field.nin" do
obj = MongoidProject.create(:title => 'Sir')
@ability.can :read, MongoidProject, :title.nin => ["Lord", "Madam"]
@ability.can :read, :mongoid_projects, :title.nin => ["Lord", "Madam"]
@ability.can?(:read, obj).should == true
MongoidProject.accessible_by(@ability, :read).should == [obj]
@ -108,7 +108,7 @@ if ENV["MODEL_ADAPTER"] == "mongoid"
it "should handle :field.size" do
obj = MongoidProject.create(:titles => ['Palatin', 'Margrave'])
@ability.can :read, MongoidProject, :titles.size => 2
@ability.can :read, :mongoid_projects, :titles.size => 2
@ability.can?(:read, obj).should == true
MongoidProject.accessible_by(@ability, :read).should == [obj]
@ -118,7 +118,7 @@ if ENV["MODEL_ADAPTER"] == "mongoid"
it "should handle :field.exists" do
obj = MongoidProject.create(:titles => ['Palatin', 'Margrave'])
@ability.can :read, MongoidProject, :titles.exists => true
@ability.can :read, :mongoid_projects, :titles.exists => true
@ability.can?(:read, obj).should == true
MongoidProject.accessible_by(@ability, :read).should == [obj]
@ -128,7 +128,7 @@ if ENV["MODEL_ADAPTER"] == "mongoid"
it "should handle :field.gt" do
obj = MongoidProject.create(:age => 50)
@ability.can :read, MongoidProject, :age.gt => 45
@ability.can :read, :mongoid_projects, :age.gt => 45
@ability.can?(:read, obj).should == true
MongoidProject.accessible_by(@ability, :read).should == [obj]
@ -138,7 +138,7 @@ if ENV["MODEL_ADAPTER"] == "mongoid"
it "should handle instance not saved to database" do
obj = MongoidProject.new(:title => 'Sir')
@ability.can :read, MongoidProject, :title.in => ["Sir", "Madam"]
@ability.can :read, :mongoid_projects, :title.in => ["Sir", "Madam"]
@ability.can?(:read, obj).should == true
# accessible_by only returns saved records
@ -151,15 +151,15 @@ if ENV["MODEL_ADAPTER"] == "mongoid"
it "should call where with matching ability conditions" do
obj = MongoidProject.create(:foo => {:bar => 1})
@ability.can :read, MongoidProject, :foo => {:bar => 1}
@ability.can :read, :mongoid_projects, :foo => {:bar => 1}
MongoidProject.accessible_by(@ability, :read).entries.first.should == obj
end
it "should exclude from the result if set to cannot" do
obj = MongoidProject.create(:bar => 1)
obj2 = MongoidProject.create(:bar => 2)
@ability.can :read, MongoidProject
@ability.cannot :read, MongoidProject, :bar => 2
@ability.can :read, :mongoid_projects
@ability.cannot :read, :mongoid_projects, :bar => 2
MongoidProject.accessible_by(@ability, :read).entries.should == [obj]
end
@ -167,13 +167,13 @@ if ENV["MODEL_ADAPTER"] == "mongoid"
obj = MongoidProject.create(:bar => 1)
obj2 = MongoidProject.create(:bar => 2)
obj3 = MongoidProject.create(:bar => 3)
@ability.can :read, MongoidProject, :bar => 1
@ability.can :read, MongoidProject, :bar => 2
@ability.can :read, :mongoid_projects, :bar => 1
@ability.can :read, :mongoid_projects, :bar => 2
MongoidProject.accessible_by(@ability, :read).entries.should =~ [obj, obj2]
end
it "should not allow to fetch records when ability with just block present" do
@ability.can :read, MongoidProject do
@ability.can :read, :mongoid_projects do
false
end
lambda {