ActiveRecord中回调的顺序排序
ActiveRecord中回调的顺序排序
我在使用ActiveRecord时遇到了一些关于回调函数排序的问题。根据Rails的指南,在创建对象时,回调函数的顺序如下:\n
- \n
- before_validation
- after_validation
- before_save
- around_save
- before_create
- around_create
- after_create
- after_save
- after_commit/after_rollback
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n我的模型中有两个回调函数。一个是用于after_save(在创建和更新时运行),另一个是用于after_create。在创建时,我希望after_create回调函数在after_save回调函数之后运行。如何在ActiveRecord中实现这个目标?谢谢。
回调函数在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不太可靠。
祝你的项目顺利进行!