Permalink
Browse files

Added a second parameter to the build and create method for has_one t…

…hat controls whether the existing association should be replaced (which means nullifying its foreign key as well). By default this is true, but false can be passed to prevent it.

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@1392 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
  • Loading branch information...
1 parent 5c2e0fe commit 2bdaff4a4e9a3813b4e4e24ff3d3b0aa53b088fc @dhh dhh committed Jun 6, 2005
@@ -1,5 +1,7 @@
*SVN*
+* Added a second parameter to the build and create method for has_one that controls whether the existing association should be replaced (which means nullifying its foreign key as well). By default this is true, but false can be passed to prevent it.
+
* Using transactional fixtures now causes the data to be loaded only once.
* Added fixture accessor methods that can be used when instantiated fixtures are disabled.
@@ -676,8 +676,9 @@ def add_multiple_associated_save_callbacks(association_name)
def association_constructor_method(constructor, association_name, association_class_name, association_class_primary_key_name, options, association_proxy_class)
define_method("#{constructor}_#{association_name}") do |*params|
- attributees = params.first unless params.empty?
- association = instance_variable_get("@#{association_name}")
+ attributees = params.first unless params.empty?
+ replace_existing = params[1].nil? ? true : params[1]
+ association = instance_variable_get("@#{association_name}")
if association.nil?
association = association_proxy_class.new(self,
@@ -686,7 +687,7 @@ def association_constructor_method(constructor, association_name, association_cl
instance_variable_set("@#{association_name}", association)
end
- association.send(constructor, attributees)
+ association.send(constructor, attributees, replace_existing)
end
end
@@ -7,6 +7,24 @@ def initialize(owner, association_name, association_class_name, association_clas
construct_sql
end
+ def create(attributes = {}, replace_existing = true)
+ record = build(attributes, replace_existing)
+ record.save
+ record
+ end
+
+ def build(attributes = {}, replace_existing = true)
+ record = @association_class.new(attributes)
+
+ if replace_existing
+ replace(record, true)
+ else
+ record[@association_class_primary_key_name] = @owner.id unless @owner.new_record?
+ end
+
+ record
+ end
+
def replace(obj, dont_save = false)
load_target
unless @target.nil?
@@ -97,6 +97,35 @@ def test_natural_assignment_to_nil
# account is dependent, therefore is destroyed when reference to owner is lost
assert_raises(ActiveRecord::RecordNotFound) { Account.find(old_account_id) }
end
+
+ def test_assignment_without_replacement
+ apple = Firm.create("name" => "Apple")
+ citibank = Account.create("credit_limit" => 10)
+ apple.account = citibank
+ assert_equal apple.id, citibank.firm_id
+
+ hsbc = apple.build_account({ :credit_limit => 20}, false)
+ assert_equal apple.id, hsbc.firm_id
+ hsbc.save
+ assert_equal apple.id, citibank.firm_id
+
+ nykredit = apple.create_account({ :credit_limit => 30}, false)
+ assert_equal apple.id, nykredit.firm_id
+ assert_equal apple.id, citibank.firm_id
+ assert_equal apple.id, hsbc.firm_id
+ end
+
+ def test_assignment_without_replacement_on_create
+ apple = Firm.create("name" => "Apple")
+ citibank = Account.create("credit_limit" => 10)
+ apple.account = citibank
+ assert_equal apple.id, citibank.firm_id
+
+ hsbc = apple.create_account({ :name => "HSBC", :credit_limit => 10}, false)
+ assert_equal apple.id, hsbc.firm_id
+ hsbc.save
+ assert_equal apple.id, citibank.firm_id
+ end
def test_dependence
firm = Firm.find(1)

0 comments on commit 2bdaff4

Please sign in to comment.