我的before_save
模型中的Message
定义如下:
class Message < ActiveRecord::Base
before_save lambda { foo(publisher); bar }
end
当我这样做时:
my_message.update_attributes(:created_at => ...)
foo
和bar
已执行。
有时,我想在不执行foo
和bar
的情况下更新邮件的字段。
如何在不执行created_at
和foo
的情况下更新bar
字段(在数据库中)?
答案 0 :(得分:34)
在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所提及的技巧。
答案 1 :(得分:17)
update_all
不会触发回调
my_message.update_all(:created_at => ...)
# OR
Message.update_all({:created_at => ...}, {:id => my_message.id})
答案 2 :(得分:6)
使用touch方法。它很优雅,完全符合您的要求
答案 3 :(得分:1)
您还可以使before_save
操作有条件。
所以添加一些字段/实例变量,只有当你想跳过它时才设置它,并在你的方法中检查它。
E.g。
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 => ...)
答案 4 :(得分:0)
update_column
或update_columns
是距update_attributes
最近的方法,它可以避免回调,而无需手动绕过任何内容。