可能是重复问题:
如何避免运行ActiveRecord回调函数?
我有这样的模型:
class Vote < ActiveRecord::Base
after_save :add_points_to_user
.....
end
是否有办法强制模型在保存时跳过调用add_points_to_user
方法?可能类似于ActiveRecord#delete
和ActiveRecord#destroy
的区别吗?
可能是重复问题:
如何避免运行ActiveRecord回调函数?
我有这样的模型:
class Vote < ActiveRecord::Base
after_save :add_points_to_user
.....
end
是否有办法强制模型在保存时跳过调用add_points_to_user
方法?可能类似于ActiveRecord#delete
和ActiveRecord#destroy
的区别吗?
对于Rails 3,ActiveSupport::Callbacks 可以提供所需的控制。我刚刚在一个数据集成场景中面临着同样的挑战,需要跳过本来很有用的回调函数。你可以批量重置回调函数或使用 skip_callback 来进行有选择性地禁用,像这样:
Vote.skip_callback(:save, :after, :add_points_to_user)
之后您可以对投票实例进行操作,但会禁止: 向用户添加积分
User.set_callback :save, :after, :add_points_to_user
请注意,如果在这两个调用之间执行的任何操作可能引发异常,您应该在其周围加上 begin(-rescue)-ensure 块。 - Timoskip_callback
声明性地设置一个 :if
选项,如 if: lambda { @skip_callbacks == true }
,并编写包装需要执行此操作的方法:def some_special_operation!; @skip_callbacks = true; do_something; save!; @skip_callbacks = false; end
。可以使用上下文管理器方法来设置/取消实例变量并生成块,但如果您经常需要这样做,则可能存在某些问题;-) 编辑 哎呀,我讨厌SO评论换行限制。 - chesskip_callback
和set_callback
如何影响回调序列。如果我正确地阅读了源代码,它们实际上会删除并重新添加回调。默认情况下,回调将被添加到链的末尾。在设置时,您可以使用:prepend => :true
将其强制添加到链的开头。如果skip/set实际上进行了停用/重新启用而不影响顺序,那就太好了。我的示例在这个答案中。 - Mark Berryattr_accessor :skip_my_callback
和
after_save :my_callback, unless: :skip_my_callback
然后在需要跳过它时,在保存之前设置 my_instance.skip_my_callback = true
。 - Rachel Hogue以下适用于Rails 2、Rails 3和Rails 4:
http://guides.rubyonrails.org/v3.2.13/active_record_validations_callbacks.html#skipping-callbacks
该网页提供了一个跳过回调的方法列表,并解释了不加谨慎使用这些方法会带来危险。根据知识共享署名-相同方式共享3.0许可条款,在此处重印。
12 跳过回调
与验证类似,也可以跳过回调。但是,应该谨慎使用这些方法,因为重要的业务规则和应用程序逻辑可能保存在回调中。不了解潜在影响地绕过它们可能会导致数据无效。
- decrement
- decrement_counter
- delete
- delete_all
- find_by_sql
- increment
- increment_counter
- toggle
- touch
- update_column
- update_all
- update_counters
vote.save(:validate => false)
更多信息请点击这里
如果要跳过回调和验证,可以使用 update_column v(3.1) 或 update_all。
vote = Vote.first
vote.update_column(:subject, 'CallBacks')
显然,这只适用于ActiveRecord 3.1。
或者:
Vote.where('id = ?', YourID).update_all(:subject => 'CallBacks')
最后还有一个finally选项,这会跳过所有步骤:
execute "UPDATE votes SET subject = 'CallBacks' WHERE id = YourID"
好的,最后一个不太美观。
对于 Rails 2,但不适用于 Rails 3,您可以使用以下代码:
object.send(:create_without_callbacks)
object.send(:update_without_callbacks)