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

时间:2011-08-30 13:15:01

标签: ruby-on-rails ruby-on-rails-3 before-filter update-attributes before-save

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

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

当我这样做时:

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

foobar已执行。

有时,我想在不执行foobar的情况下更新邮件的字段。

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

5 个答案:

答案 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})

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

答案 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_columnupdate_columns是距update_attributes最近的方法,它可以避免回调,而无需手动绕过任何内容。