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
を実行せずに?
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で言及されているトリックを実行します。
update_all
はコールバックをトリガーしません
my_message.update_all(:created_at => ...)
# OR
Message.update_all({:created_at => ...}, {:id => my_message.id})
touch メソッドを使用します。それはエレガントであり、あなたが望むものを正確に行います
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 => ...)
update_column
またはupdate_columns
はupdate_attributes
に最も近いメソッドであり、手動で何も回避することなくコールバックを回避します。