aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--activerecord/CHANGELOG2
-rwxr-xr-xactiverecord/lib/active_record/associations.rb7
-rw-r--r--activerecord/lib/active_record/associations/has_one_association.rb18
-rwxr-xr-xactiverecord/test/associations_test.rb29
4 files changed, 53 insertions, 3 deletions
diff --git a/activerecord/CHANGELOG b/activerecord/CHANGELOG
index 7a6f18986e..98773a282f 100644
--- a/activerecord/CHANGELOG
+++ b/activerecord/CHANGELOG
@@ -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.
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb
index 53a7ea7f11..001572a2c5 100755
--- a/activerecord/lib/active_record/associations.rb
+++ b/activerecord/lib/active_record/associations.rb
@@ -676,8 +676,9 @@ module ActiveRecord
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 @@ module ActiveRecord
instance_variable_set("@#{association_name}", association)
end
- association.send(constructor, attributees)
+ association.send(constructor, attributees, replace_existing)
end
end
diff --git a/activerecord/lib/active_record/associations/has_one_association.rb b/activerecord/lib/active_record/associations/has_one_association.rb
index d917f0a799..a6a80083f4 100644
--- a/activerecord/lib/active_record/associations/has_one_association.rb
+++ b/activerecord/lib/active_record/associations/has_one_association.rb
@@ -7,6 +7,24 @@ module ActiveRecord
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?
diff --git a/activerecord/test/associations_test.rb b/activerecord/test/associations_test.rb
index 03fd2b263d..7269c10c1d 100755
--- a/activerecord/test/associations_test.rb
+++ b/activerecord/test/associations_test.rb
@@ -97,6 +97,35 @@ class HasOneAssociationsTest < Test::Unit::TestCase
# 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)