ActiveRecord中回调的顺序排序

19 浏览
0 Comments

ActiveRecord中回调的顺序排序

我在使用ActiveRecord时遇到了一些关于回调函数排序的问题。根据Rails的指南,在创建对象时,回调函数的顺序如下:\n

    \n

  • before_validation
  • \n

  • after_validation
  • \n

  • before_save
  • \n

  • around_save
  • \n

  • before_create
  • \n

  • around_create
  • \n

  • after_create
  • \n

  • after_save
  • \n

  • after_commit/after_rollback
  • \n

\n我的模型中有两个回调函数。一个是用于after_save(在创建和更新时运行),另一个是用于after_create。在创建时,我希望after_create回调函数在after_save回调函数之后运行。如何在ActiveRecord中实现这个目标?谢谢。

0
0 Comments

回调函数在ActiveRecord中的顺序

在Rails中不要改变回调函数的行为,即使你知道如何改变,这样做会使以后的应用程序开发更加困难,而是改变代码的位置。

你对回调函数的名称过于纠结,它们运行的时间更重要。

以下是我们对你的设计的了解,不做任何关于最佳实现方式的假设...

- 在创建新记录后运行一个方法

- 在更新旧记录后运行一个方法

以下是你似乎为了简化编程而改变设计决策的地方,但这样做违反了最佳实践...

- 由于某种原因,你相信更新方法应该在每次保存后运行(after_save),而不是在更新后运行(after_update)

- 由于某种原因,你相信创建方法应该在更新方法之后运行(这是一种不健康的代码链接)

从技术上讲,用于创建和更新的部分应该分开为第三个方法,并由after_create和after_update调用,这样你的代码自身就有了文档,也更容易理解。

所有这些都相对重要,因为大多数有经验的程序员强调,只有当没有其他合理的方法时,才应该使用回调函数,因为它们在解决难以排查的问题时很难概念化。

解决方法1 - Rails的方式

after_save应该仅用于需要在更新和创建时运行的代码。任何需要在其中一个运行的代码都应该被拆分为较小的方法,然后根据需要由after_update和after_create调用,以保持代码的DRY原则。

解决方法2和3 - 重构旧代码而不改变设计

1. 设置一个工作测试,确保你的代码在你期望的位置失败和成功

2. after_save必须运行 - 所以我们知道它必须存在。我们将它包装在一个名为'update_method_code'的方法中,以封装它。

3. 将'update_method_code'的方法定义移动到模型或服务对象的某个地方。

4. 在after_save中保留对'update_method_code'的方法调用。

5. 以前在after_create中的代码 - 将其包装在一个名为'new_object_code'的方法中,以封装它。

6. 将'new_object_code'的方法定义移动到模型或服务对象的某个地方。

在这里,你有几个选择...

- 你可以让'update_method_code'使用四种activerecord生命周期检查之一来测试调用方法'new_object_code'。这不好,因为它会创建可见性问题,并且如果一个失败,其余的也会失败。这个方法不如按照Rails的方式使用after_update/after_create简单。

- 你可以使用已经构建好的Rails方法。after_save :update_method_code on: :create 来触发'update_method_code'。参见这里的示例Rails Guide for transactions。请记住,即使你的其他after_save调用没有运行,这个方法也可能运行...所以,这个方法比只是遵循Rails的方式使用after_update/after_create不太可靠。

祝你的项目顺利进行!

0