Ruby-on-rails 如何在不执行“before_save”的情况下“update_attributes”?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7243729/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 01:52:52  来源:igfitidea点击:

How to "update_attributes" without executing "before_save"?

ruby-on-railsruby-on-rails-3before-filterupdate-attributesbefore-save

提问by Misha Moroshko

I have a before_savein my Messagemodel defined like this:

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

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

When I do:

当我做:

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

fooand barare executed.

foo并被bar处决。

Sometimes, I would like to update message's fields without executing fooand bar.

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

How could I update, for example, the created_atfield (in the database) without executing fooand bar?

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

回答by jbescoyez

In rails 3.1 you will use update_column.

在 rails 3.1 中,您将使用update_column

Otherwise:

除此以外:

In general way, the most elegant way to bypass callbacks is the following:

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

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

Then, you can do:

然后,你可以这样做:

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

Or, just for one record:

或者,仅针对一个记录:

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

If you need it specifically for a Timeattribute, then touchwill do the trick as mentioned by @lucapette .

如果您专门为某个Time属性需要它,那么touch将执行@lucapette 提到的技巧。

回答by fl00r

update_allwon't trigger callbacks

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

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

回答by lucapette

Use the touchmethod. It's elegant and does exactly what you want

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

回答by nathanvda

You could also make your before_saveaction conditional.

你也可以让你的before_save行动有条件。

So add some field/instance variable, and set it only if you want to skip it, and check that in your method.

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

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

and then somewhere write

然后在某处写

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

回答by Archonic

update_columnor update_columnsis the closest method to update_attributesand it avoids callbacks without having to manually circumvent anything.

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