ActiveRecord中的回调顺序

时间:2019-01-29 12:24:33

标签: ruby-on-rails activerecord

我在ActiveRecord中订购回调时遇到了一些问题。根据Rails guides的说法,在创建对象时,回调的顺序如下:

  • before_validation
  • after_validation
  • 之前保存
  • around_save
  • 之前创建
  • around_create
  • after_create
  • after_save
  • after_commit / after_rollback

我的模型中有两个回调。一个用于after_save(在创建和更新时运行),第二个用于after_create。在创建时,我希望after_create回调仅在after_save回调之后运行。如何在ActiveRecord中完成此操作?谢谢。

1 个答案:

答案 0 :(得分:0)

请勿更改滑轨call_backs的行为-即使您知道怎么做,也会使以后在应用程序上工作变得困难-更改代码的放置位置。 / p>

您太迷恋call_backs的名称了。它们何时运行更重要。

这是我们对您的设计所了解的,而没有做出关于哪种设计是实现它的最佳方式的假设...

  • 您有一种在创建新记录后运行的方法
  • 您有一种方法可以在更新旧记录后运行

在这里您似乎可以更改设计决策,以使编程更容易-但这样做会破坏最佳实践...

  • 出于某些原因,您认为更新方法应该每次(after_save)而不是after_update)运行
  • 出于某种原因,您认为创建方法应该在更新方法之后运行(这是不健康的代码链)

从技术上讲,创建和更新所需的部分应分为第三种方法,并分别由after_createafter_update调用,这样您的代码便会自行记录并易于理解。

所有这些都是相对重要的-大多数有经验的程序员强调,您应该仅在没有其他合理方法的情况下才使用call_backs-由于在解决晦涩难懂的问题时很难进行概念化。


解决方案1-The Rails Way

after_save仅应用于需要同时运行更新和创建的代码。任何需要运行的代码都应分解为较小的方法,然后由after_updateafter_create根据需要进行调用,以使其保持DRY。

解决方案2和3,无需更改设计即可重构旧代码

  1. 设置工作测试以确保您的代码失败并在您期望的地方成功
  2. after_save必须运行-因此我们知道它必须存在。我们将其包装在称为“ update_method_code ”的方法中以对其进行封装。
  3. 将“ update_method_code ”的方法定义移至模型或服务对象中的某个位置。
  4. after_save中保留对“ update_method_code ”的方法调用。

由于我们从技术上没有进行任何更改,因此测试应该是绿色的。

  1. 您之前在after_create中进行了编码-将其包装在称为“ new_object_code ”的方法中,以便对其进行封装。
  2. 将“ new_object_code ”的方法定义移至模型或服务对象中的某个位置。

这是您可以选择的地方...

  • 您可以使用以下四个选项之一进行“ update_method_code ”测试 activerecord lifecycle checks测试调用方法 'new_object_code'。这不好,因为它会引起可见性问题 意思是如果一个失败了,其余的就失败了。用非常粗暴的方式 确保您的“ new_object_code”条件仅在 ' update_method_code '

  • 您使用已构建的Rails方法。 after_save :update_method_code on: :create触发“ update_method_code ”。请参见此处的示例Rails Guide for transactions。请记住,即使您的其他after_save调用没有运行,它也可能会运行...因此,再次说明,此方法比简单地遵循Rails Way和使用after_update / {{1} }。


祝您的项目好运!