From baadcb923b2c335cff48c8d683317db0b88496d1 Mon Sep 17 00:00:00 2001 From: Dmitry Afanasyev Date: Fri, 6 Jan 2012 01:21:11 +0400 Subject: [PATCH] Fixed bug with params for actions that build new instances with namespaced models --- lib/cancan/controller_resource.rb | 5 ++++- spec/cancan/controller_resource_spec.rb | 20 ++++++++++++++++++-- spec/spec_helper.rb | 15 +++++++++++++++ 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/lib/cancan/controller_resource.rb b/lib/cancan/controller_resource.rb index 7f29d61..93e5430 100644 --- a/lib/cancan/controller_resource.rb +++ b/lib/cancan/controller_resource.rb @@ -82,7 +82,10 @@ module CanCan end def build_resource - resource = resource_base.new(@params[name] || {}) + params = @options[:class] \ + ? @params[@options[:class].to_s.underscore.gsub('/', '_')] \ + : @params[name] || {} + resource = resource_base.new(params) resource.send("#{parent_name}=", parent_resource) if @options[:singleton] && parent_resource initial_attributes.each do |attr_name, value| resource.send("#{attr_name}=", value) diff --git a/spec/cancan/controller_resource_spec.rb b/spec/cancan/controller_resource_spec.rb index 21493f9..c89480c 100644 --- a/spec/cancan/controller_resource_spec.rb +++ b/spec/cancan/controller_resource_spec.rb @@ -62,6 +62,14 @@ describe CanCan::ControllerResource do @controller.instance_variable_get(:@project).name.should == "foobar" end + it "should build a new resource for namespaced model with hash if params[:id] is not specified" do + project = Sub::Project.create! + @params.merge!(:action => "create", 'sub_project' => {:name => "foobar"}) + resource = CanCan::ControllerResource.new(@controller, :class => ::Sub::Project) + resource.load_resource + @controller.instance_variable_get(:@project).name.should == "foobar" + end + it "should build a new resource with attributes from current ability" do @params.merge!(:action => "new") @ability.can(:create, Project, :name => "from conditions") @@ -324,6 +332,14 @@ describe CanCan::ControllerResource do @controller.instance_variable_get(:@project).should == project end + it "should load the model using a custom namespaced class" do + project = Sub::Project.create! + @params.merge!(:action => "show", :id => project.id) + resource = CanCan::ControllerResource.new(@controller, :class => ::Sub::Project) + resource.load_resource + @controller.instance_variable_get(:@project).should == project + end + 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 } @@ -339,7 +355,7 @@ describe CanCan::ControllerResource do lambda { resource.load_and_authorize_resource }.should raise_error(CanCan::AccessDenied) @controller.instance_variable_get(:@custom_project).should == project end - + it "should load resource using custom ID param" do project = Project.create! @params.merge!(:action => "show", :the_project => project.id) @@ -347,7 +363,7 @@ describe CanCan::ControllerResource do resource.load_resource @controller.instance_variable_get(:@project).should == project end - + it "should load resource using custom find_by attribute" do project = Project.create!(:name => "foo") @params.merge!(:action => "show", :id => "foo") diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 9576275..620af5d 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -31,6 +31,21 @@ class Category < SuperModel::Base has_many :projects end +module Sub + class Project < SuperModel::Base + belongs_to :category + 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 + class Project < SuperModel::Base belongs_to :category attr_accessor :category # why doesn't SuperModel do this automatically?