如何跳过ActiveRecord回调?

Jak*_*old 76 ruby-on-rails rails-activerecord

可能重复:
如何避免运行ActiveRecord回调?

我有这样的模特

class Vote < ActiveRecord::Base  
    after_save :add_points_to_user

    .....
end
Run Code Online (Sandbox Code Playgroud)

是否有可能以某种方式迫使模型add_points_to_user在保存时跳过呼叫?可能像ActiveRecord#deletevs ActiveRecord#destroy

tar*_*ate 165

对于Rails 3,ActiveSupport :: Callbacks为您提供必要的控制.在数据集成场景中,我只是面临同样的挑战,需要将通常需要的回调放在一边.您可以重置reset_callbacks,或使用skip_callback来明智地禁用,如下所示:

Vote.skip_callback(:save, :after, :add_points_to_user)
Run Code Online (Sandbox Code Playgroud)

..之后你可以使用以下命令对Vote实例进行操作:add_points_to_user被禁止

  • 如果您不想永久删除回调,但只说一个创建/保存,那么您必须在完成跳过回调后重新启用它:`User.set_callback:save,:after,:add_points_to_user`另外请注意,如果你在2次调用之间做的事情可能引发异常,你应该把它包装在begin(-rescue)-ensure-block周围. (40认同)
  • 我可能建议的是,在类上使用`:if`选项声明`skip_callback`,如`if:lambda {@skip_callbacks == true}`,并编写方法来包装需要执行此操作的情况: `def some_special_operation!; @skip_callbacks = true; 做一点事; 保存!; @skip_callbacks = false; end`可以使用上下文管理器方法来设置/取消设置ivar并产生一个块,但是如果你需要这么多可能有些错误;-)**编辑**呃,我讨厌SO评论换行限制. (7认同)
  • 特定实例是否有类似的功能? (6认同)
  • 注意 `skip_callback` 和 `set_callback` 如何影响回调序列。如果我正确阅读 [源代码](http://api.rubyonrails.org/v3.2.16/classes/ActiveSupport/Callbacks/ClassMethods.html#method-i-set_callback),它们实际上会删除并重新添加回调。默认情况下,它被添加到链的 *end*。设置时,可以使用`:prepend =&gt; :true` 强制到链的开头。如果跳过/设置实际上在不影响序列的情况下进行了停用/重新激活,那就太好了。我的例子在 [this answer](http://stackoverflow.com/a/22676587/550712) 中。 (3认同)
  • 这不是线程安全的。因此,如果您在多线程服务器上运行它,请务必小心。 (3认同)

she*_*onh 45

以下适用于导轨2,导轨3和导轨4:

http://guides.rubyonrails.org/v3.2.13/active_record_validations_callbacks.html#skipping-callbacks

它提供了一个跳过回调的方法列表,解释了为什么在没有仔细考虑的情况下使用它们是危险的.根据知识共享署名 - 相同方式共享3.0许可的规定在此重印.

12跳过回调

与验证一样,也可以跳过回调.但是,应谨慎使用这些方法,因为重要的业务规则和应用程序逻辑可能会保留在回调中.在不了解潜在影响的情况下绕过它们可能会导致数据无效.

  • 减量
  • decrement_counter
  • 删除
  • 删除所有
  • 的find_by_sql
  • 增量
  • increment_counter
  • 切换
  • 触摸
  • update_column
  • 全部更新
  • update_counters


Sta*_*ght 29

对于Rails 2,但不是Rails 3,您可以使用这些:

object.send(:create_without_callbacks)
object.send(:update_without_callbacks)
Run Code Online (Sandbox Code Playgroud)

  • 不幸的是,这不再适用于Rails 3 :( (7认同)
  • 那个`Model`有误导性,那些是AR实例的方法,而不是classmethods,所以`record.send(:create_without_callbacks)`. (3认同)
  • 有关Rails 2和Rails 3的建议,请参阅我的回答. (2认同)

wor*_*mer 29

这将跳过您的验证:

vote.save(:validate => false)
Run Code Online (Sandbox Code Playgroud)

更多信息在这里

要跳过回调和验证,可以使用update_column v(3.1)或update_all

vote = Vote.first
vote.update_column(:subject, 'CallBacks')
Run Code Online (Sandbox Code Playgroud)

这只适用于ActiveRecord 3.1

要么:

Vote.where('id = ?', YourID).update_all(:subject => 'CallBacks')
Run Code Online (Sandbox Code Playgroud)

最后你还有我最后的选择,这将跳过everthing:

execute "UPDATE votes SET subject = 'CallBacks' WHERE id = YourID"
Run Code Online (Sandbox Code Playgroud)

好吧,最后一个它不是那么漂亮.

  • 这不会跳过回调,只是验证 (5认同)
  • update_column也可以,除了上面的语法不正确.它预计有两个参数:vote.update_column(:subject,'CallBacks') (3认同)