如何在不执行“before_save”的情况下“update_attributes”?

我的Message模型中的before_save定义如下:

  class Message < ActiveRecord::Base before_save lambda { foo(publisher); bar } end 

当我做:

  my_message.update_attributes(:created_at => ...) 

foobar被执行。

有时,我想更新消息的字段而不执行foobar

如何在不执行foobar情况下更新created_at字段(在数据库中)?

在rails 3.1中,您将使用update_column 。

除此以外:

一般来说,绕过回调最优雅的方法如下:

 class Message < ActiveRecord::Base cattr_accessor :skip_callbacks before_save lambda { foo(publisher); bar }, :unless => :skip_callbacks # let's say you do not want this callback to be triggered when you perform batch operations end 

然后,你可以这样做:

 Message.skip_callbacks = true # for multiple records my_message.update_attributes(:created_at => ...) Message.skip_callbacks = false # reset 

或者,只为一个记录:

 my_message.update_attributes(:created_at => ..., :skip_callbacks => true) 

如果你需要专门为Time属性,那么touch将完成@luttette提到的技巧。

update_all不会触发回调

 my_message.update_all(:created_at => ...) # OR Message.update_all({:created_at => ...}, {:id => my_message.id}) 

http://apidock.com/rails/ActiveRecord/Base/update_all/class

使用触摸方法。 它很优雅,完全符合您的要求

您还可以使before_save操作有条件。

因此,添加一些字段/实例变量,并仅在您想要跳过它时设置它,并在您的方法中检查它。

例如

 before_save :do_foo_and_bar_if_allowed attr_accessor :skip_before_save def do_foo_and_bar_if_allowed unless @skip_before_save.present? foo(publisher) bar end end 

然后在某处写

 my_message.skip_before_save = true my_message.update_attributes(:created_at => ...) 

update_columnupdate_columns是最接近update_attributes方法,它避免了回调而不必手动规避任何事情。