web-dev-qa-db-ja.com

「before_save」を実行せずに「update_attributes」を作成する方法は?

before_saveMessageモデルで次のように定義されています:

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

私がする時:

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

foobarが実行されます。

時々、foobarを実行せずにメッセージのフィールドを更新したいことがあります。

たとえば、created_atフィールド(データベース内)fooおよびbarを実行せずに?

24
Misha Moroshko

Rails 3.1では pdate_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

または、1つのレコードのみ:

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

特にTime属性に必要な場合は、touchが@lucapetteで言及されているトリックを実行します。

34
jbescoyez

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

17
fl00r

touch メソッドを使用します。それはエレガントであり、あなたが望むものを正確に行います

6
lucapette

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 => ...)
1
nathanvda

update_columnまたはupdate_columnsupdate_attributesに最も近いメソッドであり、手動で何も回避することなくコールバックを回避します。

0
Archonic