24

before_save我的模型中有一个Message这样定义的:

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

当我做:

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

foo并被bar执行。

有时,我想在不执行fooand的情况下更新消息的字段bar

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

4

5 回答 5

35

在 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 所述的技巧进行操作。

于 2011-08-30T13:33:35.427 回答
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

于 2011-08-30T13:18:14.040 回答
6

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

于 2011-08-30T13:19:43.643 回答
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 => ...)
于 2011-08-30T13:34:00.607 回答
1

update_columnorupdate_columns是最接近的方法update_attributes,它避免了回调,而无需手动规避任何事情。

于 2017-10-13T23:33:11.477 回答