首页 > 解决方案 > ActiveRecord 中的回调排序

问题描述

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

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

标签: ruby-on-railsactiverecord

解决方案


不要改变 rails 的行为call_backs——即使你知道怎么做,这会使以后在应用程序上工作变得更加困难——改变你放置代码的位置。

你太沉迷于call_backs. 他们什么时候跑更重要。

以下是我们对您的设计的了解,而无需假设哪些是实现它的最佳方式......

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

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

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

从技术上讲,创建和更新所需的部分应该分成第三种方法并由两者调用after_create&after_update以便您的代码记录自己并且更容易理解。

所有这些都是相对重要的——因为大多数有经验的程序员都强调你应该只call_backs在没有其他方法合理的情况下使用——因为他们在解决模糊问题时很难概念化。


解决方案 1 - Rails 方式

after_save应该只用于需要同时运行更新和创建的代码。任何需要为其中一个或另一个运行的代码都应该被分解成更小的方法,然后根据需要由after_update&调用after_create以保持其 DRY。

解决方案 2 & 3 在不改变设计的情况下重构旧代码

  1. 设置工作测试以确保您的代码在您期望的地方失败并成功
  2. after_save必须运行——所以我们知道它必须在那里。我们将它包装在一个名为“ update_method_code ”的方法中来封装它。
  3. 将“ update_method_code ”的方法定义移动到模型或服务对象的某处。
  4. 将“ update_method_code ”的方法调用留在after_save.

因为我们在技术上没有改变任何东西,所以测试应该是绿色的。

  1. 您以前编写过代码after_create- 将其包装在一个名为“ new_object_code ”的方法中,以便对其进行封装。
  2. 将“ new_object_code ”的方法定义移动到模型或服务对象的某处。

这是你有几个选择的地方......

  • 您可以使用四个 activerecord 生命周期检查之一进行“ update_method_code ”测试,以测试调用方法“new_object_code”。这不好,因为它会产生可见性问题,并且意味着如果一个失败,其余的都会失败。它以非常严厉的方式确保您的“new_object_code”条件仅在“ update_method_code ”之后运行

  • 您使用已经构建的 Rails 方法。after_save :update_method_code on: :create触发' update_method_code '。请参阅此处的 Rails 交易指南示例。请记住,即使您的其他after_save调用没有运行,这也可能会运行......所以再一次,这种方法比简单地遵循 Rails 方式和使用after_update/更不健全after_create


祝你的项目好运!


推荐阅读