Techioz Blog

ActiveRecord コールバックの実行を回避するにはどうすればよいですか?

概要

after_save コールバックを持つモデルがいくつかあります。通常はこれで問題ありませんが、開発データの作成時など、コールバックを実行せずにモデルを保存したい場合があります。それを行う簡単な方法はありますか?似たような何か…

Person#save( :run_callbacks => false )

または

Person#save_without_callbacks

Rails のドキュメントを調べましたが、何も見つかりませんでした。ただし、私の経験では、Rails ドキュメントが必ずしもすべてを伝えているわけではありません。

アップデート

次のようなモデルからコールバックを削除する方法を説明したブログ投稿を見つけました。

Foo.after_save.clear

その方法が文書化されている場所を見つけることができませんでしたが、機能するようです。

解決策

コールバックと検証をスキップするには、update_column (Rails >= v3.1) または update_columns (Rails >= 4.0) を使用します。これらのメソッドでも、updated_at は更新されません。

#Rails >= v3.1 only
@person.update_column(:some_attribute, 'value')
#Rails >= v4.0 only
@person.update_columns(attributes)

http://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-update_column

#2: オブジェクトの作成中にも機能するコールバックのスキップ

class Person < ActiveRecord::Base
  attr_accessor :skip_some_callbacks

  before_validation :do_something
  after_validation :do_something_else

  skip_callback :validation, :before, :do_something, if: :skip_some_callbacks
  skip_callback :validation, :after, :do_something_else, if: :skip_some_callbacks
end

person = Person.new(person_params)
person.skip_some_callbacks = true
person.save

更新情報 (2020)

どうやら Rails は常に :if および :unless オプションをサポートしているため、上記のコードは次のように簡略化できます。

class Person < ActiveRecord::Base
  attr_accessor :skip_some_callbacks

  before_validation :do_something, unless: :skip_some_callbacks
  after_validation :do_something_else, unless: :skip_some_callbacks
end

person = Person.new(person_params)
person.skip_some_callbacks = true
person.save