23

我有一个before_save在这样定义我Message型号:如何在不执行“before_save”的情况下“update_attributes”?

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

当我这样做:

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

foobar被执行。

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

我怎么能更新,例如,created_at字段(在数据库中)而不执行foobar

回答

33

在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将执行@lucapette所述的技巧。

+0

看起来像一个很好的通用解决方案!一个问题:究竟是什么'Message.batch = true'呢? –

+0

这只是一面旗帜。你可以用任何你想要的来代替它。 – jbescoyez

+0

我已经用更明确的标志更新了示例。 – jbescoyez

17

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

+1

'my_message.update_all(:created_at => ...)'发出语法错误,但第二个选项正常工作! –

+1

my_message.update_all将触发'未定义的方法update_all'。 Message.update_all将会诀窍 –

+0

你可能可以使用increment_counter [如果它是一个你想增加的计数器],我相信它也会跳过回调。 – rogerdpack

6

使用touch方法。这是优雅的,而不是你想要的

+0

看起来像我需要的东西。在我的情况下,'created_at'的新值是**而不是当前时间。 –

+0

哦,有趣:) – fl00r

+0

@Misha你显然是对的。所以你可以使用http://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-update_attribute:D – lucapette

1

您还可以使您的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 => ...) 
0

update_columnupdate_columnsupdate_attributes最接近方法和它避免了回调而无需手动规避任何东西。

相关问题