diff --git a/CHANGELOG.rdoc b/CHANGELOG.rdoc index 4f313a0..c9ed045 100644 --- a/CHANGELOG.rdoc +++ b/CHANGELOG.rdoc @@ -1,3 +1,5 @@ +* Allowing :nested option to accept an array for deep nesting + * Adding :nested option to load resource method - see issue #10 * Pass :only and :except options to before filters for load/authorize resource methods. diff --git a/lib/cancan/controller_additions.rb b/lib/cancan/controller_additions.rb index 676913d..85684bc 100644 --- a/lib/cancan/controller_additions.rb +++ b/lib/cancan/controller_additions.rb @@ -41,6 +41,10 @@ module CanCan # # load_resource :nested => :author # + # Deep nesting can be defined in an array. + # + # load_resource :nested => [:publisher, :author] + # # [:+collection+] # Specify which actions are resource collection actions in addition to :+index+. This # is usually not necessary because it will try to guess depending on if an :+id+ diff --git a/lib/cancan/resource_authorization.rb b/lib/cancan/resource_authorization.rb index 5239c19..acb3aaa 100644 --- a/lib/cancan/resource_authorization.rb +++ b/lib/cancan/resource_authorization.rb @@ -34,11 +34,12 @@ module CanCan end def parent_resource - if @options[:nested] - parent = ControllerResource.new(@controller, @options[:nested]) - parent.find(@params["#{@options[:nested]}_id".to_sym]) - parent + parent = nil + [@options[:nested]].flatten.compact.each do |name| + parent = ControllerResource.new(@controller, name, parent) + parent.find(@params["#{name}_id".to_sym]) end + parent end def model_name diff --git a/spec/cancan/resource_authorization_spec.rb b/spec/cancan/resource_authorization_spec.rb index ccda257..d8b8189 100644 --- a/spec/cancan/resource_authorization_spec.rb +++ b/spec/cancan/resource_authorization_spec.rb @@ -84,22 +84,16 @@ describe CanCan::ResourceAuthorization do end it "should load nested resource and fetch other resource through the association" do - person = Object.new - stub(Person).find(456) { person } - stub(person).abilities.stub!.find(123) { :some_ability } + stub(Person).find(456).stub!.abilities.stub!.find(123) { :some_ability } authorization = CanCan::ResourceAuthorization.new(@controller, {:controller => "abilities", :action => "show", :id => 123, :person_id => 456}, {:nested => :person}) authorization.load_resource - @controller.instance_variable_get(:@person).should == person @controller.instance_variable_get(:@ability).should == :some_ability end - it "should load nested resource and fetch build resource through the association" do - person = Object.new - stub(Person).find(456) { person } - stub(person).abilities.stub!.build({:foo => :bar}) { :some_ability } - authorization = CanCan::ResourceAuthorization.new(@controller, {:controller => "abilities", :action => "new", :person_id => 456, :ability => {:foo => :bar}}, {:nested => :person}) + it "should load nested resource and build resource through a deep association" do + stub(Person).find(456).stub!.behaviors.stub!.find(789).stub!.abilities.stub!.build(nil) { :some_ability } + authorization = CanCan::ResourceAuthorization.new(@controller, {:controller => "abilities", :action => "new", :person_id => 456, :behavior_id => 789}, {:nested => [:person, :behavior]}) authorization.load_resource - @controller.instance_variable_get(:@person).should == person @controller.instance_variable_get(:@ability).should == :some_ability end end