如何跳过 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_callback
和set_callback
之间的代码产生了一些错误,回调可以被永远跳过并且不再设置。需要重新启动服务器才能使其再次工作。最糟糕的是:整个班级都将跳过此回调!这意味着该类的所有实例都将跳过此回调!如果你想使用它,请小心。在使用这种方法处理 skip
和 set
回调时,我的应用程序遇到了大问题。
感谢 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 文档的回调?的主要内容,如果未能解决你的问题,请参考以下文章