Rails 3:确保before_save回调在其他回调之后被调用

时间:2021-05-02 23:27:34

Is there a way to ensure that a given before_save callback is executed after all other before_save callbacks in ActiveRecord short of actually ordering them so in the code?

是否有一种方法可以确保在ActiveRecord中所有其他的before_save回调都被执行后,在实际的代码中没有对它们进行排序?

I'm writing an external library that includes some before_save functionality but in order to be effective it really needs to be called after all others. I can get around it but it involves giving up dirty attributes which I really don't want to!

我正在编写一个外部库,其中包含一些before_save功能,但为了有效,它确实需要在所有其他功能之后调用。我可以绕过它,但它包括放弃我真的不想要的肮脏属性!

-- edit --

——编辑

I didn't realise in this that dirty attributes are maintained after the save of the model. So @page.attribute_was will still work after the yield in an around_save.

在这一点上,我没有意识到,脏属性是在保存模型之后被维护的。所以@page。attribute_was仍然会在around_save中执行收益率之后的工作。

2 个解决方案

#1


5  

You could make the callback you want executed last an around_save callback. Check out the list of available callbacks and see if you can simply use a different callback "bucket" for some of your callbacks to ensure they are executed in the desired order.

您可以将您希望执行的回调设置为around_save回调。查看可用的回调列表,看看是否可以简单地使用一个不同的回调“bucket”,以确保它们按照所需的顺序执行。

If you still end up with multiple before_save callbacks and need one to trigger last, you may want to create custom callbacks, like maybe define_model_callbacks :split_save, registering your regular before_save callbacks as before_split_save callbacks, the one you want executed last as a after_split_save callback, and then just a single before_save callback that runs those two groups of callbacks (run_callbacks :split_save). See ActiveModel::Callbacks for more on how to do this.

如果你仍然得到多个before_save回调,需要一个触发最后,您可能想要创建自定义回调,比如define_model_callbacks:split_save,注册常规before_save before_split_save回调,回调一个你想要执行最后after_split_save回调,然后就一个before_save调这两组运行的回调(run_callbacks:split_save)。有关如何执行此操作的更多信息,请参见ActiveModel::回调。

#2


1  

So this was to get around giving up dirty attributes by using ordered before_<type> callbacks instead of after_<type> callbacks, since dirty attributes changes get wiped after saving.

因此,这是为了避免放弃脏属性,使用orderbefore_ <类型> 回调而不是after_ <类型> 回调,因为脏属性更改在保存后会被删除。

It turns out, however, that the changes are still accessible in after_<type> callbacks.

然而,在after_ <类型> 回调中仍然可以访问更改。

I only worked this out after trawling through Vestal Versions code to see how they did it.

我只是在浏览完灶神星版本的代码后才得出这个结论的。

Facepalm.

Facepalm指。

I'm accepting Carl's answer because it's a pretty complete answer to the rather badly presented question.

我接受卡尔的回答,因为这是一个相当完整的回答,来回答这个相当糟糕的问题。

#1


5  

You could make the callback you want executed last an around_save callback. Check out the list of available callbacks and see if you can simply use a different callback "bucket" for some of your callbacks to ensure they are executed in the desired order.

您可以将您希望执行的回调设置为around_save回调。查看可用的回调列表,看看是否可以简单地使用一个不同的回调“bucket”,以确保它们按照所需的顺序执行。

If you still end up with multiple before_save callbacks and need one to trigger last, you may want to create custom callbacks, like maybe define_model_callbacks :split_save, registering your regular before_save callbacks as before_split_save callbacks, the one you want executed last as a after_split_save callback, and then just a single before_save callback that runs those two groups of callbacks (run_callbacks :split_save). See ActiveModel::Callbacks for more on how to do this.

如果你仍然得到多个before_save回调,需要一个触发最后,您可能想要创建自定义回调,比如define_model_callbacks:split_save,注册常规before_save before_split_save回调,回调一个你想要执行最后after_split_save回调,然后就一个before_save调这两组运行的回调(run_callbacks:split_save)。有关如何执行此操作的更多信息,请参见ActiveModel::回调。

#2


1  

So this was to get around giving up dirty attributes by using ordered before_<type> callbacks instead of after_<type> callbacks, since dirty attributes changes get wiped after saving.

因此,这是为了避免放弃脏属性,使用orderbefore_ <类型> 回调而不是after_ <类型> 回调,因为脏属性更改在保存后会被删除。

It turns out, however, that the changes are still accessible in after_<type> callbacks.

然而,在after_ <类型> 回调中仍然可以访问更改。

I only worked this out after trawling through Vestal Versions code to see how they did it.

我只是在浏览完灶神星版本的代码后才得出这个结论的。

Facepalm.

Facepalm指。

I'm accepting Carl's answer because it's a pretty complete answer to the rather badly presented question.

我接受卡尔的回答,因为这是一个相当完整的回答,来回答这个相当糟糕的问题。