Skip to content
Browse files

use Item.new instead of build_item for singleton resource so it doesn…

…'t mess up database - closes #304
  • Loading branch information...
1 parent fdd5ad0 commit 3f6cecbfcf91613756128734d9bb115c68d92333 @ryanb committed Mar 15, 2011
Showing with 16 additions and 11 deletions.
  1. +12 −8 lib/cancan/controller_resource.rb
  2. +3 −3 spec/cancan/controller_resource_spec.rb
  3. +1 −0 spec/spec_helper.rb
View
20 lib/cancan/controller_resource.rb
@@ -82,10 +82,10 @@ def load_collection
end
def build_resource
- method_name = @options[:singleton] && resource_base.respond_to?("build_#{name}") ? "build_#{name}" : "new"
- resource = resource_base.send(method_name, @params[name] || {})
- initial_attributes.each do |name, value|
- resource.send("#{name}=", value)
+ resource = resource_base.new(@params[name] || {})
+ resource.send("#{parent_name}=", parent_resource) if @options[:singleton] && parent_resource
+ initial_attributes.each do |attr_name, value|
+ resource.send("#{attr_name}=", value)
end
resource
end
@@ -97,8 +97,8 @@ def initial_attributes
end
def find_resource
- if @options[:singleton] && resource_base.respond_to?(name)
- resource_base.send(name)
+ if @options[:singleton] && parent_resource.respond_to?(name)
+ parent_resource.send(name)
else
@options[:find_by] ? resource_base.send("find_by_#{@options[:find_by]}!", id_param) : resource_base.find(id_param)
end
@@ -155,7 +155,7 @@ def collection_instance
def resource_base
if @options[:through]
if parent_resource
- @options[:singleton] ? parent_resource : parent_resource.send(@options[:through_association] || name.to_s.pluralize)
+ @options[:singleton] ? resource_class : parent_resource.send(@options[:through_association] || name.to_s.pluralize)
elsif @options[:shallow]
resource_class
else
@@ -166,9 +166,13 @@ def resource_base
end
end
+ def parent_name
+ @options[:through] && [@options[:through]].flatten.detect { |i| fetch_parent(i) }
+ end
+
# The object to load this resource through.
def parent_resource
- @options[:through] && [@options[:through]].flatten.map { |i| fetch_parent(i) }.compact.first
+ parent_name && fetch_parent(parent_name)
end
def fetch_parent(name)
View
6 spec/cancan/controller_resource_spec.rb
@@ -268,14 +268,14 @@
@controller.instance_variable_get(:@project).should == :some_project
end
- it "should build record through has_one association with :singleton option" do
+ it "should not build record through has_one association with :singleton option because it can cause it to delete it in the database" do
@params.merge!(:action => "create", :project => {:name => "foobar"})
- category = Object.new
+ category = Category.new
@controller.instance_variable_set(:@category, category)
- stub(category).build_project { |attributes| Project.new(attributes) }
resource = CanCan::ControllerResource.new(@controller, :through => :category, :singleton => true)
resource.load_resource
@controller.instance_variable_get(:@project).name.should == "foobar"
+ @controller.instance_variable_get(:@project).category.should == category
end
it "should find record through has_one association with :singleton and :shallow options" do
View
1 spec/spec_helper.rb
@@ -29,4 +29,5 @@ class Category < SuperModel::Base
class Project < SuperModel::Base
belongs_to :category
+ attr_accessor :category # why doesn't SuperModel do this automatically?
end

1 comment on commit 3f6cecb

@flop
flop commented on 3f6cecb Apr 4, 2011

Just got a little suprise with this change, before/after_add callbacks on has_many association are not called any more when initializing nested resources with 'new' instead of 'build'
[Edit : Sorry wrong commit, 'new' was already used before but callbacks aren't called anyway ;)]

Please sign in to comment.
Something went wrong with that request. Please try again.