From c11ffb6fd165a30ea95f50e6ae59de5ffb5c9d94 Mon Sep 17 00:00:00 2001 From: Ryan Bates Date: Tue, 21 Sep 2010 11:42:47 -0700 Subject: [PATCH] support loading resource :through method along with instance variable - closes #146 --- lib/cancan/controller_additions.rb | 2 +- lib/cancan/controller_resource.rb | 10 +++++++++- spec/cancan/controller_resource_spec.rb | 12 +++++++++++- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/lib/cancan/controller_additions.rb b/lib/cancan/controller_additions.rb index 3db1f1f..b832278 100644 --- a/lib/cancan/controller_additions.rb +++ b/lib/cancan/controller_additions.rb @@ -69,7 +69,7 @@ module CanCan # Does not apply before filter to given actions. # # [:+through+] - # Load this resource through another one. This should match the name of the parent instance variable. + # Load this resource through another one. This should match the name of the parent instance variable or method. # # [:+shallow+] # Pass +true+ to allow this resource to be loaded directly when parent is +nil+. Defaults to +false+. diff --git a/lib/cancan/controller_resource.rb b/lib/cancan/controller_resource.rb index 62435f8..3db00ba 100644 --- a/lib/cancan/controller_resource.rb +++ b/lib/cancan/controller_resource.rb @@ -145,7 +145,15 @@ module CanCan # The object to load this resource through. def parent_resource - @options[:through] && [@options[:through]].flatten.map { |i| @controller.instance_variable_get("@#{i}") }.compact.first + @options[:through] && [@options[:through]].flatten.map { |i| fetch_parent(i) }.compact.first + end + + def fetch_parent(name) + if @controller.instance_variable_defined? "@#{name}" + @controller.instance_variable_get("@#{name}") + elsif @controller.respond_to? name + @controller.send(name) + end end def name diff --git a/spec/cancan/controller_resource_spec.rb b/spec/cancan/controller_resource_spec.rb index c8bb86c..34a8b2b 100644 --- a/spec/cancan/controller_resource_spec.rb +++ b/spec/cancan/controller_resource_spec.rb @@ -164,7 +164,7 @@ describe CanCan::ControllerResource do @controller.instance_variable_get(:@project).should == :some_project end - it "should load resource through the association of another parent resource" do + it "should load resource through the association of another parent resource using instance variable" do @params.merge!(:action => "show", :id => 123) category = Object.new @controller.instance_variable_set(:@category, category) @@ -174,6 +174,16 @@ describe CanCan::ControllerResource do @controller.instance_variable_get(:@project).should == :some_project end + it "should load resource through the association of another parent resource using method" do + @params.merge!(:action => "show", :id => 123) + category = Object.new + stub(@controller).category { category } + stub(category).projects.stub!.find(123) { :some_project } + resource = CanCan::ControllerResource.new(@controller, :through => :category) + resource.load_resource + @controller.instance_variable_get(:@project).should == :some_project + end + it "should not load through parent resource if instance isn't loaded when shallow" do @params.merge!(:action => "show", :id => 123) stub(Project).find(123) { :some_project }