提交 ebd7cc6f 编写于 作者: C Chris Thompson 提交者: Aaron Patterson

Fix #8856 Ensure has_one association=(associate) triggers save.

activerecord/lib/active_record/associations.rb states:

    # [association=(associate)]
    #   Assigns the associate object, extracts the primary key, sets it as the foreign key,
    #   and saves the associate object.

Since commit 42dd5d9f to fix #7191, this
is no longer the case if the associate has changed, but is the same
object. For example:

    # Pirate has_one :ship
    pirate = Pirate.create!(catchphrase: "A Pirate")
    ship = pirate.build_ship(name: 'old name')
    ship.save!

    ship.name = 'new name'
    pirate.ship = ship

That last line should trigger a save. Although we are not changing the
association, the associate (ship) has changed.
上级 e8e2f010
* Trigger a save on `has_one association=(associate)` when the associate contents have changed.
Fix #8856.
*Chris Thompson*
* Abort a rake task when missing db/structure.sql like `db:schema:load` task. * Abort a rake task when missing db/structure.sql like `db:schema:load` task.
*kennyj* *kennyj*
......
...@@ -25,9 +25,8 @@ def replace(record, save = true) ...@@ -25,9 +25,8 @@ def replace(record, save = true)
raise_on_type_mismatch!(record) if record raise_on_type_mismatch!(record) if record
load_target load_target
# If target and record are nil, or target is equal to record, return self.target if !(target || record)
# we don't need to have transaction. if (target != record) || record.changed?
if (target || record) && target != record
transaction_if(save) do transaction_if(save) do
remove_target!(options[:dependent]) if target && !target.destroyed? remove_target!(options[:dependent]) if target && !target.destroyed?
......
...@@ -522,4 +522,20 @@ def test_has_one_transaction ...@@ -522,4 +522,20 @@ def test_has_one_transaction
account = Account.find(2) account = Account.find(2)
assert_queries { company.account = account } assert_queries { company.account = account }
end end
def test_has_one_assignment_triggers_save_on_change
pirate = Pirate.create!(catchphrase: "Don' botharrr talkin' like one, savvy?")
ship = pirate.build_ship(name: 'old name')
ship.save!
ship.name = 'new name'
assert ship.changed?
assert_queries(2) do
# One query for updating name and second query for updating pirate_id
pirate.ship = ship
end
assert_equal 'new name', pirate.ship.reload.name
end
end end
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册