如何跳过 Mongoid 文档的回调?

Posted

技术标签:

【中文标题】如何跳过 Mongoid 文档的回调?【英文标题】:How to skip callbacks on Mongoid Documents? 【发布时间】:2011-03-04 01:54:55 【问题描述】:

我的问题与How to skip ActiveRecord callbacks? 类似,但我使用的是 Mongoid 而不是 AR,似乎在当前版本的 Mongoid 中还没有实现,所以我想知道应该是什么优雅的解决方案来实现它。 (如有必要)。

【问题讨论】:

哪个版本的 Mongoid ? Mongoid 1.9.0 还是 Mongoid 2.0.0.beta ? 【参考方案1】:

是的,你可以!

Mongoid 基于 ActiveModel 构建,ActiveModel 有一个skip_callback function。你可以像这样使用skip_callback

# skip the callback
MyModelClass.skip_callback(:save, :before, :ensure_foo_is_not_bar)

# rescue any errors to ensure callback is restored afterwords
begin
  my_model_instance.update_attributes :foo => 'bar'
rescue
  puts "Error from 'my_model_instance.update_attributes': #$!"
end

# restore the callback for future calls
MyModelClass.set_callback(:save, :before, :ensure_foo_is_not_bar)

我在大型应用程序中顺利使用它。有关详细信息,请参阅 Jeff Kreeftmeijer 的这篇博文:

http://jeffkreeftmeijer.com/2010/disabling-activemodel-callbacks/

【讨论】:

如果有一种方法可以像关闭验证一样关闭所有回调,那就太好了:u.save!(validate: false) 将是 u.save!(callbacks: false) 非常感谢,这项工作适用于我的测试套件中的跳过回调。 这可能会导致一个非常大的问题。如果skip_callbackset_callback 之间的代码产生了一些错误,回调可以被永远跳过并且不再设置。需要重新启动服务器才能使其再次工作。最糟糕的是:整个班级都将跳过此回调!这意味着该类的所有实例都将跳过此回调!如果你想使用它,请小心。在使用这种方法处理 skipset 回调时,我的应用程序遇到了大问题。 感谢 Victor 指出这个问题。我已经更新了答案中的代码以使用 resuce 块来防止错误禁用回调。【参考方案2】:

使用 Mongoid 原子操作(设置、取消设置等)可能更容易:

https://docs.mongodb.com/mongoid/current/tutorials/mongoid-persistence/#atomic

这些不会触发回调。

编辑:Mongoid 3 说他们不会触发回调。我看到他们在 Mongoid 2 中触发回调。所以YMMV

【讨论】:

这也适用于 Mongoid 4。试图弄清楚如何在父文档中添加一个计数器,并将级联回调设置为 true。【参考方案3】:

我最终使用了 Brian Armstrong 的建议并简单地调用了

person.set(name:"Robert Pulson")

在我的保存后回调中。

【讨论】:

【参考方案4】:

当您想要在不触发大量项目的所有回调的情况下进行更新时,通常会出现这种情况。这可以通过下降到驱动程序来完成:

将“x”字段中的“foo”替换为“bar”。

User.all.each do |u|
  User.collection.where( _id: u.id ).update( 
    "$set" =>  :x => u.x.gsub('foo', 'bar') 
  )
end

【讨论】:

【参考方案5】:

我搜索代码。在 Mongoid 中也没有办法避免回调。在 1.9 和 2.0 版本中。

您需要为此提出补丁或功能请求。

【讨论】:

谢谢,是的,我也在审查 2.0.0.beta 并且没有跳过回调支持......让我们看看 AR 是如何做到的,然后在我的 mongoid 版本上实现它。

以上是关于如何跳过 Mongoid 文档的回调?的主要内容,如果未能解决你的问题,请参考以下文章

Ruby MongoId:回调中的竞争条件

不会触发Mongoid after / before_remove回调

管理 mongoid 迁移

Mongoid / Mongodb 和查询嵌入文档

Mongoid:嵌入文档在父级构造时自动初始化

Mongoid 按值或默认值查询