Rails - execution sequence of after create callback & nested attributes
Asked Answered
G

1

14

I have a simple set up of User and UserProfile model with User has_one :user_profile and UserProfile belongs_to :user.

But I am unable to wrap my head around how Rails defines execution order of after_create callback and accepts_nested_attributes_for defined in my model. Lets consider these two cases.

Case 1:

class User < ActiveRecord::Base
  has_one :user_profile
  accepts_nested_attributes_for :user_profile
  after_create :test_test
end

Now, if I create a user(with user_profile_attributes hash too) via the console, the after_create callback is triggered after the user and its user profile is created.

Case 2: If the after_create is placed at the top,

class User < ActiveRecord::Base
  after_create :test_test
  has_one :user_profile
  accepts_nested_attributes_for :user_profile
end

the callback is triggered after a user has been created but before creating a user profile.

Is this the way it is expected to function. What does Rails do internally here? Is the execution sequence simply determined by the order of the code?

Where do I start to dig deeper into or debug this ?

Genitourinary answered 9/3, 2012 at 9:23 Comment(2)
I would test this again, order of code in the form of callbacks has nothing to do with execution order..Pricilla
Using inverse_of might be useful to solve dependencies and saving problems on create or on save. e.g. has_one :user_profile, inverse_of: :userBendicta
B
13

The order of the declarations in your model can have an impact on the execution order of the code. This is a source for various weird things. (for example, currently callback definitions and has_and_belongs_to_many associations are order dependent: https://github.com/rails/rails/pull/8674 )

To debug the issue you need to browse the rails source. Since your problem has to do with execution order, callbacks and nested attributes I would start by reading up on:

This gives you the necessary background to dig deeper. You'll notice that accepts_nested_attributes_for calls into add_autosave_association_callbacks https://github.com/rails/rails/blob/master/activerecord/lib/active_record/autosave_association.rb#L173 This method adds an after_create callback and as far as I know callbacks are executed in order of definition.

Bromley answered 2/1, 2013 at 13:36 Comment(3)
Thank you. This was exactly what I was running into. My model had after_create callbacks running and they were placed BEFORE the has_many definitions. In the after_create I was updating an attribute with update_attribute (in certain cases) which was then causing the rest of the has_many chain to fail updating meaning that my has_many :through relationships were NOT saving whatsoever. Moving the after_create AFTER my relationship definitions fixed the issue. Crazy. Thank you!!!Pyorrhea
The (not so obscure?) issue discussed in this post is a thing. I was bitten by it, and I fixed the problem by moving the 'after_update' callback definition to below the has_many & accepts_nested_attributes_for definitions, in my model -- as described above.Goliath
@DonnFelker yes, moving my after_create below my accepts_nested_attributes fixed it for me too, thanks.Jug

© 2022 - 2024 — McMap. All rights reserved.