mirror of https://github.com/rails/rails
has_one maintains the association with separate after_create/after_update
This way parent models can get their own after_create and after_update callbacks fired after has_one has done its job.
This commit is contained in:
parent
fc8c072988
commit
5b86c3e5bb
|
@ -1,5 +1,8 @@
|
|||
*Rails 3.1.0 (unreleased)*
|
||||
|
||||
* has_one maintains the association with separate after_create/after_update instead
|
||||
of a single after_save. [fxn]
|
||||
|
||||
* The following code:
|
||||
|
||||
Model.limit(10).scoping { Model.count }
|
||||
|
|
|
@ -167,7 +167,16 @@ module ActiveRecord
|
|||
else
|
||||
if reflection.macro == :has_one
|
||||
define_method(save_method) { save_has_one_association(reflection) }
|
||||
after_save save_method
|
||||
# Configures two callbacks instead of a single after_save so that
|
||||
# the model may rely on their execution order relative to its
|
||||
# own callbacks.
|
||||
#
|
||||
# For example, given that after_creates run before after_saves, if
|
||||
# we configured instead an after_save there would be no way to fire
|
||||
# a custom after_create callback after the child association gets
|
||||
# created.
|
||||
after_create save_method
|
||||
after_update save_method
|
||||
else
|
||||
define_method(save_method) { save_belongs_to_association(reflection) }
|
||||
before_save save_method
|
||||
|
|
|
@ -17,6 +17,7 @@ require 'models/tag'
|
|||
require 'models/tagging'
|
||||
require 'models/treasure'
|
||||
require 'models/company'
|
||||
require 'models/eye'
|
||||
|
||||
class TestAutosaveAssociationsInGeneral < ActiveRecord::TestCase
|
||||
def test_autosave_should_be_a_valid_option_for_has_one
|
||||
|
@ -170,6 +171,25 @@ class TestDefaultAutosaveAssociationOnAHasOneAssociation < ActiveRecord::TestCas
|
|||
firm.account = Account.find(:first).clone
|
||||
assert_queries(2) { firm.save! }
|
||||
end
|
||||
|
||||
def test_callbacks_firing_order_on_create
|
||||
eye = Eye.create(:iris_attributes => {:color => 'honey'})
|
||||
assert_equal [true, false], eye.after_create_callbacks_stack
|
||||
end
|
||||
|
||||
def test_callbacks_firing_order_on_update
|
||||
eye = Eye.create(:iris_attributes => {:color => 'honey'})
|
||||
eye.update_attributes(:iris_attributes => {:color => 'green'})
|
||||
assert_equal [true, false], eye.after_update_callbacks_stack
|
||||
end
|
||||
|
||||
def test_callbacks_firing_order_on_save
|
||||
eye = Eye.create(:iris_attributes => {:color => 'honey'})
|
||||
assert_equal [false, false], eye.after_save_callbacks_stack
|
||||
|
||||
eye.update_attributes(:iris_attributes => {:color => 'blue'})
|
||||
assert_equal [false, false, false, false], eye.after_save_callbacks_stack
|
||||
end
|
||||
end
|
||||
|
||||
class TestDefaultAutosaveAssociationOnABelongsToAssociation < ActiveRecord::TestCase
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
class Eye < ActiveRecord::Base
|
||||
attr_reader :after_create_callbacks_stack
|
||||
attr_reader :after_update_callbacks_stack
|
||||
attr_reader :after_save_callbacks_stack
|
||||
|
||||
# Callbacks configured before the ones has_one sets up.
|
||||
after_create :trace_after_create
|
||||
after_update :trace_after_update
|
||||
after_save :trace_after_save
|
||||
|
||||
has_one :iris
|
||||
accepts_nested_attributes_for :iris
|
||||
|
||||
# Callbacks configured after the ones has_one sets up.
|
||||
after_create :trace_after_create2
|
||||
after_update :trace_after_update2
|
||||
after_save :trace_after_save2
|
||||
|
||||
def trace_after_create
|
||||
(@after_create_callbacks_stack ||= []) << iris.new_record?
|
||||
end
|
||||
alias trace_after_create2 trace_after_create
|
||||
|
||||
def trace_after_update
|
||||
(@after_update_callbacks_stack ||= []) << iris.changed?
|
||||
end
|
||||
alias trace_after_update2 trace_after_update
|
||||
|
||||
def trace_after_save
|
||||
(@after_save_callbacks_stack ||= []) << iris.changed?
|
||||
end
|
||||
alias trace_after_save2 trace_after_save
|
||||
end
|
||||
|
||||
class Iris < ActiveRecord::Base
|
||||
belongs_to :eye
|
||||
end
|
|
@ -156,6 +156,11 @@ ActiveRecord::Schema.define do
|
|||
t.integer :company_id
|
||||
end
|
||||
|
||||
create_table :iris, :force => true do |t|
|
||||
t.integer :eye
|
||||
t.string :color
|
||||
end
|
||||
|
||||
create_table :customers, :force => true do |t|
|
||||
t.string :name
|
||||
t.integer :balance, :default => 0
|
||||
|
@ -194,6 +199,9 @@ ActiveRecord::Schema.define do
|
|||
t.integer :car_id
|
||||
end
|
||||
|
||||
create_table :eyes, :force => true do |t|
|
||||
end
|
||||
|
||||
create_table :tyres, :force => true do |t|
|
||||
t.integer :car_id
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue