cleaning up some internal specs and names

This commit is contained in:
Ryan Bates 2010-09-03 14:00:46 -07:00
parent a744377ac9
commit 721939babd
7 changed files with 145 additions and 142 deletions

View File

@ -209,7 +209,7 @@ module CanCan
def attributes_for(action, subject) def attributes_for(action, subject)
attributes = {} attributes = {}
relevant_can_definitions(action, subject).map do |can_definition| relevant_can_definitions(action, subject).map do |can_definition|
attributes.merge!(can_definition.new_attributes) if can_definition.base_behavior attributes.merge!(can_definition.attributes_from_conditions) if can_definition.base_behavior
end end
attributes attributes
end end

View File

@ -67,7 +67,7 @@ module CanCan
hash hash
end end
def new_attributes def attributes_from_conditions
attributes = {} attributes = {}
@conditions.each do |key, value| @conditions.each do |key, value|
attributes[key] = value unless [Array, Range, Hash].include? value.class attributes[key] = value unless [Array, Range, Hash].include? value.class

View File

@ -2,7 +2,7 @@ require "spec_helper"
describe CanCan::ActiveRecordAdditions do describe CanCan::ActiveRecordAdditions do
before(:each) do before(:each) do
@model_class = Class.new(Person) @model_class = Class.new(Project)
stub(@model_class).scoped { :scoped_stub } stub(@model_class).scoped { :scoped_stub }
@model_class.send(:include, CanCan::ActiveRecordAdditions) @model_class.send(:include, CanCan::ActiveRecordAdditions)
@ability = Object.new @ability = Object.new

View File

@ -1,5 +1,6 @@
require "spec_helper" require "spec_helper"
# Most of CanDefinition functionality is tested in Ability specs
describe CanCan::CanDefinition do describe CanCan::CanDefinition do
before(:each) do before(:each) do
@conditions = {} @conditions = {}

View File

@ -2,7 +2,7 @@ require "spec_helper"
describe CanCan::ControllerResource do describe CanCan::ControllerResource do
before(:each) do before(:each) do
@params = HashWithIndifferentAccess.new(:controller => "abilities") @params = HashWithIndifferentAccess.new(:controller => "projects")
@controller = Object.new # simple stub for now @controller = Object.new # simple stub for now
stub(@controller).params { @params } stub(@controller).params { @params }
stub(@controller).current_ability.stub!.attributes_for { {} } stub(@controller).current_ability.stub!.attributes_for { {} }
@ -10,74 +10,74 @@ describe CanCan::ControllerResource do
it "should load the resource into an instance variable if params[:id] is specified" do it "should load the resource into an instance variable if params[:id] is specified" do
@params.merge!(:action => "show", :id => 123) @params.merge!(:action => "show", :id => 123)
stub(Ability).find(123) { :some_resource } stub(Project).find(123) { :some_project }
resource = CanCan::ControllerResource.new(@controller) resource = CanCan::ControllerResource.new(@controller)
resource.load_resource resource.load_resource
@controller.instance_variable_get(:@ability).should == :some_resource @controller.instance_variable_get(:@project).should == :some_project
end end
it "should not load resource into an instance variable if already set" do it "should not load resource into an instance variable if already set" do
@params.merge!(:action => "show", :id => 123) @params.merge!(:action => "show", :id => 123)
@controller.instance_variable_set(:@ability, :some_ability) @controller.instance_variable_set(:@project, :some_project)
resource = CanCan::ControllerResource.new(@controller) resource = CanCan::ControllerResource.new(@controller)
resource.load_resource resource.load_resource
@controller.instance_variable_get(:@ability).should == :some_ability @controller.instance_variable_get(:@project).should == :some_project
end end
it "should properly load resource for namespaced controller" do it "should properly load resource for namespaced controller" do
@params.merge!(:controller => "admin/abilities", :action => "show", :id => 123) @params.merge!(:controller => "admin/projects", :action => "show", :id => 123)
stub(Ability).find(123) { :some_resource } stub(Project).find(123) { :some_project }
resource = CanCan::ControllerResource.new(@controller) resource = CanCan::ControllerResource.new(@controller)
resource.load_resource resource.load_resource
@controller.instance_variable_get(:@ability).should == :some_resource @controller.instance_variable_get(:@project).should == :some_project
end end
it "should properly load resource for namespaced controller when using '::' for namespace" do it "should properly load resource for namespaced controller when using '::' for namespace" do
@params.merge!(:controller => "Admin::AbilitiesController", :action => "show", :id => 123) @params.merge!(:controller => "Admin::ProjectsController", :action => "show", :id => 123)
stub(Ability).find(123) { :some_resource } stub(Project).find(123) { :some_project }
resource = CanCan::ControllerResource.new(@controller) resource = CanCan::ControllerResource.new(@controller)
resource.load_resource resource.load_resource
@controller.instance_variable_get(:@ability).should == :some_resource @controller.instance_variable_get(:@project).should == :some_project
end end
it "should build a new resource with hash if params[:id] is not specified" do it "should build a new resource with hash if params[:id] is not specified" do
@params.merge!(:action => "create", :ability => {:foo => "bar"}) @params.merge!(:action => "create", :project => {:foo => "bar"})
stub(Ability).new("foo" => "bar") { :some_resource } stub(Project).new("foo" => "bar") { :some_project }
resource = CanCan::ControllerResource.new(@controller) resource = CanCan::ControllerResource.new(@controller)
resource.load_resource resource.load_resource
@controller.instance_variable_get(:@ability).should == :some_resource @controller.instance_variable_get(:@project).should == :some_project
end end
it "should build a new resource with attributes from current ability" do it "should build a new resource with attributes from current ability" do
@params[:controller] = "people" @params[:controller] = "projects"
@params[:action] = "new" @params[:action] = "new"
person = Object.new project = Object.new
mock(Person).new { person } mock(Project).new { project }
mock(person).name = "foobar" mock(project).name = "foobar"
stub(@controller).current_ability.stub!.attributes_for(:new, Person) { {:name => "foobar"} } stub(@controller).current_ability.stub!.attributes_for(:new, Project) { {:name => "foobar"} }
resource = CanCan::ControllerResource.new(@controller) resource = CanCan::ControllerResource.new(@controller)
resource.load_resource resource.load_resource
@controller.instance_variable_get(:@person).should == person @controller.instance_variable_get(:@project).should == project
end end
it "should not build a resource when on index action" do it "should not build a resource when on index action" do
@params[:action] = "index" @params[:action] = "index"
resource = CanCan::ControllerResource.new(@controller) resource = CanCan::ControllerResource.new(@controller)
resource.load_resource resource.load_resource
@controller.instance_variable_get(:@ability).should be_nil @controller.instance_variable_get(:@project).should be_nil
end end
it "should perform authorization using controller action and loaded model" do it "should perform authorization using controller action and loaded model" do
@params[:action] = "show" @params[:action] = "show"
@controller.instance_variable_set(:@ability, :some_resource) @controller.instance_variable_set(:@project, :some_project)
stub(@controller).authorize!(:show, :some_resource) { raise CanCan::AccessDenied } stub(@controller).authorize!(:show, :some_project) { raise CanCan::AccessDenied }
resource = CanCan::ControllerResource.new(@controller) resource = CanCan::ControllerResource.new(@controller)
lambda { resource.authorize_resource }.should raise_error(CanCan::AccessDenied) lambda { resource.authorize_resource }.should raise_error(CanCan::AccessDenied)
end end
it "should perform authorization using controller action and non loaded model" do it "should perform authorization using controller action and non loaded model" do
@params[:action] = "show" @params[:action] = "show"
stub(@controller).authorize!(:show, Ability) { raise CanCan::AccessDenied } stub(@controller).authorize!(:show, Project) { raise CanCan::AccessDenied }
resource = CanCan::ControllerResource.new(@controller) resource = CanCan::ControllerResource.new(@controller)
lambda { resource.authorize_resource }.should raise_error(CanCan::AccessDenied) lambda { resource.authorize_resource }.should raise_error(CanCan::AccessDenied)
end end
@ -94,155 +94,147 @@ describe CanCan::ControllerResource do
@params[:action] = "sort" @params[:action] = "sort"
resource = CanCan::ControllerResource.new(@controller, :collection => [:sort, :list]) resource = CanCan::ControllerResource.new(@controller, :collection => [:sort, :list])
resource.load_resource resource.load_resource
@controller.instance_variable_get(:@ability).should be_nil @controller.instance_variable_get(:@project).should be_nil
end end
it "should build a resource when on custom new action even when params[:id] exists" do it "should build a resource when on custom new action even when params[:id] exists" do
@params.merge!(:action => "build", :id => 123) @params.merge!(:action => "build", :id => 123)
stub(Ability).new { :some_resource } stub(Project).new { :some_project }
resource = CanCan::ControllerResource.new(@controller, :new => :build) resource = CanCan::ControllerResource.new(@controller, :new => :build)
resource.load_resource resource.load_resource
@controller.instance_variable_get(:@ability).should == :some_resource @controller.instance_variable_get(:@project).should == :some_project
end end
it "should not try to load resource for other action if params[:id] is undefined" do it "should not try to load resource for other action if params[:id] is undefined" do
@params[:action] = "list" @params[:action] = "list"
resource = CanCan::ControllerResource.new(@controller) resource = CanCan::ControllerResource.new(@controller)
resource.load_resource resource.load_resource
@controller.instance_variable_get(:@ability).should be_nil @controller.instance_variable_get(:@project).should be_nil
end end
it "should be a parent resource when name is provided which doesn't match controller" do it "should be a parent resource when name is provided which doesn't match controller" do
resource = CanCan::ControllerResource.new(@controller, :person) resource = CanCan::ControllerResource.new(@controller, :category)
resource.should be_parent resource.should be_parent
end end
it "should not be a parent resource when name is provided which matches controller" do it "should not be a parent resource when name is provided which matches controller" do
resource = CanCan::ControllerResource.new(@controller, :ability) resource = CanCan::ControllerResource.new(@controller, :project)
resource.should_not be_parent resource.should_not be_parent
end end
it "should be parent if specified in options" do it "should be parent if specified in options" do
resource = CanCan::ControllerResource.new(@controller, :ability, {:parent => true}) resource = CanCan::ControllerResource.new(@controller, :project, {:parent => true})
resource.should be_parent resource.should be_parent
end end
it "should not be parent if specified in options" do it "should not be parent if specified in options" do
resource = CanCan::ControllerResource.new(@controller, :person, {:parent => false}) resource = CanCan::ControllerResource.new(@controller, :category, {:parent => false})
resource.should_not be_parent resource.should_not be_parent
end end
it "should load parent resource through proper id parameter when supplying a resource with a different name" do it "should load parent resource through proper id parameter" do
@params.merge!(:action => "index", :person_id => 123) @params.merge!(:action => "index", :project_id => 123)
stub(Person).find(123) { :some_person } stub(Project).find(123) { :some_project }
resource = CanCan::ControllerResource.new(@controller, :person) resource = CanCan::ControllerResource.new(@controller, :project, :parent => true)
resource.load_resource resource.load_resource
@controller.instance_variable_get(:@person).should == :some_person @controller.instance_variable_get(:@project).should == :some_project
end
it "should load parent resource for collection action" do
@params.merge!(:action => "index", :person_id => 456)
stub(Person).find(456) { :some_person }
resource = CanCan::ControllerResource.new(@controller, :person)
resource.load_resource
@controller.instance_variable_get(:@person).should == :some_person
end end
it "should load resource through the association of another parent resource" do it "should load resource through the association of another parent resource" do
@params.merge!(:action => "show", :id => 123) @params.merge!(:action => "show", :id => 123)
person = Object.new category = Object.new
@controller.instance_variable_set(:@person, person) @controller.instance_variable_set(:@category, category)
stub(person).abilities.stub!.find(123) { :some_ability } stub(category).projects.stub!.find(123) { :some_project }
resource = CanCan::ControllerResource.new(@controller, :through => :person) resource = CanCan::ControllerResource.new(@controller, :through => :category)
resource.load_resource resource.load_resource
@controller.instance_variable_get(:@ability).should == :some_ability @controller.instance_variable_get(:@project).should == :some_project
end end
it "should not load through parent resource if instance isn't loaded" do it "should not load through parent resource if instance isn't loaded" do
@params.merge!(:action => "show", :id => 123) @params.merge!(:action => "show", :id => 123)
stub(Ability).find(123) { :some_ability } stub(Project).find(123) { :some_project }
resource = CanCan::ControllerResource.new(@controller, :through => :person) resource = CanCan::ControllerResource.new(@controller, :through => :category)
resource.load_resource resource.load_resource
@controller.instance_variable_get(:@ability).should == :some_ability @controller.instance_variable_get(:@project).should == :some_project
end end
it "should authorize nested resource through parent association on index action" do it "should authorize nested resource through parent association on index action" do
@params.merge!(:action => "index") @params.merge!(:action => "index")
person = Object.new category = Object.new
@controller.instance_variable_set(:@person, person) @controller.instance_variable_set(:@category, category)
stub(@controller).authorize!(:index, person => Ability) { raise CanCan::AccessDenied } stub(@controller).authorize!(:index, category => Project) { raise CanCan::AccessDenied }
resource = CanCan::ControllerResource.new(@controller, :through => :person) resource = CanCan::ControllerResource.new(@controller, :through => :category)
lambda { resource.authorize_resource }.should raise_error(CanCan::AccessDenied) lambda { resource.authorize_resource }.should raise_error(CanCan::AccessDenied)
end end
it "should load through first matching if multiple are given" do it "should load through first matching if multiple are given" do
@params.merge!(:action => "show", :id => 123) @params.merge!(:action => "show", :id => 123)
person = Object.new category = Object.new
@controller.instance_variable_set(:@person, person) @controller.instance_variable_set(:@category, category)
stub(person).abilities.stub!.find(123) { :some_ability } stub(category).projects.stub!.find(123) { :some_project }
resource = CanCan::ControllerResource.new(@controller, :through => [:thing, :person]) resource = CanCan::ControllerResource.new(@controller, :through => [:category, :user])
resource.load_resource resource.load_resource
@controller.instance_variable_get(:@ability).should == :some_ability @controller.instance_variable_get(:@project).should == :some_project
end end
it "should find record through has_one association with :singleton option" do it "should find record through has_one association with :singleton option" do
@params.merge!(:action => "show") @params.merge!(:action => "show")
person = Object.new category = Object.new
@controller.instance_variable_set(:@person, person) @controller.instance_variable_set(:@category, category)
stub(person).ability { :some_ability } stub(category).project { :some_project }
resource = CanCan::ControllerResource.new(@controller, :through => :person, :singleton => true) resource = CanCan::ControllerResource.new(@controller, :through => :category, :singleton => true)
resource.load_resource resource.load_resource
@controller.instance_variable_get(:@ability).should == :some_ability @controller.instance_variable_get(:@project).should == :some_project
end end
it "should build record through has_one association with :singleton option" do it "should build record through has_one association with :singleton option" do
@params.merge!(:action => "create", :ability => :ability_attributes) @params.merge!(:action => "create", :project => :project_attributes)
person = Object.new category = Object.new
@controller.instance_variable_set(:@person, person) @controller.instance_variable_set(:@category, category)
stub(person).build_ability(:ability_attributes) { :new_ability } stub(category).build_project(:project_attributes) { :new_project }
resource = CanCan::ControllerResource.new(@controller, :through => :person, :singleton => true) resource = CanCan::ControllerResource.new(@controller, :through => :category, :singleton => true)
resource.load_resource resource.load_resource
@controller.instance_variable_get(:@ability).should == :new_ability @controller.instance_variable_get(:@project).should == :new_project
end end
it "should only authorize :read action on parent resource" do it "should only authorize :read action on parent resource" do
@params.merge!(:action => "new", :person_id => 123) @params.merge!(:action => "new", :project_id => 123)
stub(Person).find(123) { :some_person } stub(Project).find(123) { :some_project }
stub(@controller).authorize!(:read, :some_person) { raise CanCan::AccessDenied } stub(@controller).authorize!(:read, :some_project) { raise CanCan::AccessDenied }
resource = CanCan::ControllerResource.new(@controller, :person) resource = CanCan::ControllerResource.new(@controller, :project, :parent => true)
lambda { resource.load_and_authorize_resource }.should raise_error(CanCan::AccessDenied) lambda { resource.load_and_authorize_resource }.should raise_error(CanCan::AccessDenied)
end end
it "should load the model using a custom class" do it "should load the model using a custom class" do
@params.merge!(:action => "show", :id => 123) @params.merge!(:action => "show", :id => 123)
stub(Person).find(123) { :some_resource } stub(Project).find(123) { :some_project }
resource = CanCan::ControllerResource.new(@controller, :class => Person) resource = CanCan::ControllerResource.new(@controller, :class => Project)
resource.load_resource resource.load_resource
@controller.instance_variable_get(:@ability).should == :some_resource @controller.instance_variable_get(:@project).should == :some_project
end end
it "should authorize based on resource name if class is false" do it "should authorize based on resource name if class is false" do
@params.merge!(:action => "show", :id => 123) @params.merge!(:action => "show", :id => 123)
stub(@controller).authorize!(:show, :ability) { raise CanCan::AccessDenied } stub(@controller).authorize!(:show, :project) { raise CanCan::AccessDenied }
resource = CanCan::ControllerResource.new(@controller, :class => false) resource = CanCan::ControllerResource.new(@controller, :class => false)
lambda { resource.authorize_resource }.should raise_error(CanCan::AccessDenied) lambda { resource.authorize_resource }.should raise_error(CanCan::AccessDenied)
end end
it "should load and authorize using custom instance name" do it "should load and authorize using custom instance name" do
@params.merge!(:action => "show", :id => 123) @params.merge!(:action => "show", :id => 123)
stub(Ability).find(123) { :some_ability } stub(Project).find(123) { :some_project }
stub(@controller).authorize!(:show, :some_ability) { raise CanCan::AccessDenied } stub(@controller).authorize!(:show, :some_project) { raise CanCan::AccessDenied }
resource = CanCan::ControllerResource.new(@controller, :instance_name => :custom_ability) resource = CanCan::ControllerResource.new(@controller, :instance_name => :custom_project)
lambda { resource.load_and_authorize_resource }.should raise_error(CanCan::AccessDenied) lambda { resource.load_and_authorize_resource }.should raise_error(CanCan::AccessDenied)
@controller.instance_variable_get(:@custom_ability).should == :some_ability @controller.instance_variable_get(:@custom_project).should == :some_project
end end
it "should load resource using custom find_by attribute" do it "should load resource using custom find_by attribute" do
@params.merge!(:action => "show", :id => 123) @params.merge!(:action => "show", :id => 123)
stub(Ability).find_by_name!(123) { :some_resource } stub(Project).find_by_name!(123) { :some_project }
resource = CanCan::ControllerResource.new(@controller, :find_by => :name) resource = CanCan::ControllerResource.new(@controller, :find_by => :name)
resource.load_resource resource.load_resource
@controller.instance_variable_get(:@ability).should == :some_resource @controller.instance_variable_get(:@project).should == :some_project
end end
it "should raise ImplementationRemoved when adding :name option" do it "should raise ImplementationRemoved when adding :name option" do
@ -253,13 +245,13 @@ describe CanCan::ControllerResource do
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 => Person) 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 => :person) CanCan::ControllerResource.new(@controller, :nested => :project)
}.should raise_error(CanCan::ImplementationRemoved) }.should raise_error(CanCan::ImplementationRemoved)
end end
end end

View File

@ -7,101 +7,101 @@ describe CanCan::Query do
end end
it "should have false conditions if no abilities match" do it "should have false conditions if no abilities match" do
@ability.query(:destroy, Person).conditions.should == "true=false" @ability.query(:destroy, Project).conditions.should == "true=false"
end end
it "should return hash for single `can` definition" do it "should return hash for single `can` definition" do
@ability.can :read, Person, :blocked => false, :user_id => 1 @ability.can :read, Project, :blocked => false, :user_id => 1
@ability.query(:read, Person).conditions.should == { :blocked => false, :user_id => 1 } @ability.query(:read, Project).conditions.should == { :blocked => false, :user_id => 1 }
end end
it "should merge multiple can definitions into single SQL string joining with OR" do it "should merge multiple can definitions into single SQL string joining with OR" do
@ability.can :read, Person, :blocked => false @ability.can :read, Project, :blocked => false
@ability.can :read, Person, :admin => true @ability.can :read, Project, :admin => true
@ability.query(:read, Person).conditions.should == "(admin=true) OR (blocked=false)" @ability.query(:read, Project).conditions.should == "(admin=true) OR (blocked=false)"
end end
it "should merge multiple can definitions into single SQL string joining with OR and AND" do it "should merge multiple can definitions into single SQL string joining with OR and AND" do
@ability.can :read, Person, :blocked => false, :active => true @ability.can :read, Project, :blocked => false, :active => true
@ability.can :read, Person, :admin => true @ability.can :read, Project, :admin => true
@ability.query(:read, Person).conditions.should orderlessly_match("(blocked=false AND active=true) OR (admin=true)") @ability.query(:read, Project).conditions.should orderlessly_match("(blocked=false AND active=true) OR (admin=true)")
end end
it "should merge multiple can definitions into single SQL string joining with OR and AND" do it "should merge multiple can definitions into single SQL string joining with OR and AND" do
@ability.can :read, Person, :blocked => false, :active => true @ability.can :read, Project, :blocked => false, :active => true
@ability.can :read, Person, :admin => true @ability.can :read, Project, :admin => true
@ability.query(:read, Person).conditions.should orderlessly_match("(blocked=false AND active=true) OR (admin=true)") @ability.query(:read, Project).conditions.should orderlessly_match("(blocked=false AND active=true) OR (admin=true)")
end end
it "should return false conditions for cannot clause" do it "should return false conditions for cannot clause" do
@ability.cannot :read, Person @ability.cannot :read, Project
@ability.query(:read, Person).conditions.should == "true=false" @ability.query(:read, Project).conditions.should == "true=false"
end end
it "should return SQL for single `can` definition in front of default `cannot` condition" do it "should return SQL for single `can` definition in front of default `cannot` condition" do
@ability.cannot :read, Person @ability.cannot :read, Project
@ability.can :read, Person, :blocked => false, :user_id => 1 @ability.can :read, Project, :blocked => false, :user_id => 1
@ability.query(:read, Person).conditions.should orderlessly_match("blocked=false AND user_id=1") @ability.query(:read, Project).conditions.should orderlessly_match("blocked=false AND user_id=1")
end end
it "should return true condition for single `can` definition in front of default `can` condition" do it "should return true condition for single `can` definition in front of default `can` condition" do
@ability.can :read, Person @ability.can :read, Project
@ability.can :read, Person, :blocked => false, :user_id => 1 @ability.can :read, Project, :blocked => false, :user_id => 1
@ability.query(:read, Person).conditions.should == 'true=true' @ability.query(:read, Project).conditions.should == 'true=true'
end end
it "should return false condition for single `cannot` definition" do it "should return false condition for single `cannot` definition" do
@ability.cannot :read, Person, :blocked => true, :user_id => 1 @ability.cannot :read, Project, :blocked => true, :user_id => 1
@ability.query(:read, Person).conditions.should == 'true=false' @ability.query(:read, Project).conditions.should == 'true=false'
end end
it "should return `false condition` for single `cannot` definition in front of default `cannot` condition" do it "should return `false condition` for single `cannot` definition in front of default `cannot` condition" do
@ability.cannot :read, Person @ability.cannot :read, Project
@ability.cannot :read, Person, :blocked => true, :user_id => 1 @ability.cannot :read, Project, :blocked => true, :user_id => 1
@ability.query(:read, Person).conditions.should == 'true=false' @ability.query(:read, Project).conditions.should == 'true=false'
end end
it "should return `not (sql)` for single `cannot` definition in front of default `can` condition" do it "should return `not (sql)` for single `cannot` definition in front of default `can` condition" do
@ability.can :read, Person @ability.can :read, Project
@ability.cannot :read, Person, :blocked => true, :user_id => 1 @ability.cannot :read, Project, :blocked => true, :user_id => 1
@ability.query(:read, Person).conditions.should orderlessly_match("not (blocked=true AND user_id=1)") @ability.query(:read, Project).conditions.should orderlessly_match("not (blocked=true AND user_id=1)")
end end
it "should return appropriate sql conditions in complex case" do it "should return appropriate sql conditions in complex case" do
@ability.can :read, Person @ability.can :read, Project
@ability.can :manage, Person, :id => 1 @ability.can :manage, Project, :id => 1
@ability.can :update, Person, :manager_id => 1 @ability.can :update, Project, :manager_id => 1
@ability.cannot :update, Person, :self_managed => true @ability.cannot :update, Project, :self_managed => true
@ability.query(:update, Person).conditions.should == 'not (self_managed=true) AND ((manager_id=1) OR (id=1))' @ability.query(:update, Project).conditions.should == 'not (self_managed=true) AND ((manager_id=1) OR (id=1))'
@ability.query(:manage, Person).conditions.should == {:id=>1} @ability.query(:manage, Project).conditions.should == {:id=>1}
@ability.query(:read, Person).conditions.should == 'true=true' @ability.query(:read, Project).conditions.should == 'true=true'
end end
it "should have nil joins if no can definitions" do it "should have nil joins if no can definitions" do
@ability.query(:read, Person).joins.should be_nil @ability.query(:read, Project).joins.should be_nil
end end
it "should have nil joins if no nested hashes specified in conditions" do it "should have nil joins if no nested hashes specified in conditions" do
@ability.can :read, Person, :blocked => false @ability.can :read, Project, :blocked => false
@ability.can :read, Person, :admin => true @ability.can :read, Project, :admin => true
@ability.query(:read, Person).joins.should be_nil @ability.query(:read, Project).joins.should be_nil
end end
it "should merge separate joins into a single array" do it "should merge separate joins into a single array" do
@ability.can :read, Person, :project => { :blocked => false } @ability.can :read, Project, :project => { :blocked => false }
@ability.can :read, Person, :company => { :admin => true } @ability.can :read, Project, :company => { :admin => true }
@ability.query(:read, Person).joins.inspect.should orderlessly_match([:company, :project].inspect) @ability.query(:read, Project).joins.inspect.should orderlessly_match([:company, :project].inspect)
end end
it "should merge same joins into a single array" do it "should merge same joins into a single array" do
@ability.can :read, Person, :project => { :blocked => false } @ability.can :read, Project, :project => { :blocked => false }
@ability.can :read, Person, :project => { :admin => true } @ability.can :read, Project, :project => { :admin => true }
@ability.query(:read, Person).joins.should == [:project] @ability.query(:read, Project).joins.should == [:project]
end end
it "should merge complex, nested joins" do it "should merge complex, nested joins" do
@ability.can :read, Person, :project => { :bar => {:test => true} }, :company => { :bar => {:test => true} } @ability.can :read, Project, :project => { :bar => {:test => true} }, :company => { :bar => {:test => true} }
@ability.can :read, Person, :project => { :foo => {:bar => true}, :bar => {:zip => :zap} } @ability.can :read, Project, :project => { :foo => {:bar => true}, :bar => {:zip => :zap} }
@ability.query(:read, Person).joins.inspect.should orderlessly_match([{:project => [:bar, :foo]}, {:company => [:bar]}].inspect) @ability.query(:read, Project).joins.inspect.should orderlessly_match([{:project => [:bar, :foo]}, {:company => [:bar]}].inspect)
end end
end end

View File

@ -19,8 +19,18 @@ class Ability
end end
end end
# this class helps out in testing SQL conditions # Generic class to mimic a model
class Person class Project
attr_accessor :name
def initialize(attributes = {})
@name = attributes[:name]
end
def attributes=(attributes)
@name = attributes[:name] if attributes[:name]
end
class << self class << self
protected protected