2012-03-09 80 views
12

我有一个简单的设置UserUserProfile模型与用户has_one :user_profile和UserProfile belongs_to :userRails - 创建回调后的执行顺序和嵌套属性

但是我无法围绕我的模型中定义的定义after_create回调和accepts_nested_attributes_for的执行顺序的方式进行讨论。让我们考虑这两种情况。

案例1:

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

现在,如果我创建一个用户(与user_profile_attributes散列太)通过控制台,该after_create回调后用户触发,并创建其用户配置文件。

案例2: 如果after_create被放置在顶部,用户已经创建之后,但

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

回调触发创建用户配置文件之前。

这是它预期的功能。 Rails在内部做了什么?执行顺序是否仅由代码的顺序决定?

我该从哪里开始深入或调试呢?

+1

我会再次测试这个,回调形式的代码顺序与执行顺序无关。 – Rabbott 2012-03-15 05:37:59

+0

@Rabbott - 我明白了! – prasvin 2012-03-15 06:12:14

+0

使用'inverse_of'可能有助于解决依赖关系并在创建或保存时保存问题。例如'has_one:user_profile,inverse_of :: user' – ybart 2017-08-03 09:16:29

回答

10

模型中声明的顺序可能会影响代码的执行顺序。这是各种奇怪事物的来源。 (例如,当前的回调定义和has_and_belongs_to_many关联与订单相关:https://github.com/rails/rails/pull/8674

要调试问题,您需要浏览rails源代码。由于您的问题与执行顺序,回调和嵌套的属性,我会开始做通过阅读起来:

这给你必要的背景深入挖掘。你会注意到accepts_nested_attributes_for调用add_autosave_association_callbackshttps://github.com/rails/rails/blob/master/activerecord/lib/active_record/autosave_association.rb#L173 这种方法增加了一个after_create回调,据我所知,回调按定义顺序执行。

+2

谢谢。这正是我遇到的情况。我的模型有after_create回调运行,并且它们被放置在has_many定义之前。在after_create中,我使用update_attribute(在某些情况下)更新了一个属性,然后导致has_many链的其余部分无法更新,意味着我的has_many:通过关系不保存任何内容。在我的关系定义之后移动after_create修复了这个问题。疯。谢谢!!! – 2014-02-20 23:32:38

+0

这篇文章中讨论的(不那么晦涩?)问题是一件事情。我被它咬了,我通过在我的模型中将'after_update'回调定义移动到has_many&acceptions_attributes_for定义之下来解决了这个问题 - 如上所述。 – 2016-06-12 21:23:12

+0

@DonnFelker是的,将我的'after_create'移动到我的'accep_nested_attributes'下方,我也解决了它,谢谢。 – eggie5 2016-09-15 16:33:32