LoginSignup
0

More than 5 years have passed since last update.

インスタンスレベルで作成時のコールバックをスキップしたいときのメモ

Last updated at Posted at 2017-10-28

概要

モデルに定義されたコールバックをスキップしたい場合Model.skip_callbackが公開APIとして提供されている。しかしこのメソッドはクラスメソッドとして提供されているため、影響が全てのインスタンスに及んでしまう。

特定のインスタンスでだけコールバックをスキップする方法がないか調べたのでメモする。

結論

インスタンスレベルでコールバックをスキップする公開APIは用意されていないが、内部APIを利用して無理やりスキップすることができるようだった。

やり方

以下のように呼び出すことで、作成時のコールバックをスキップできる

ActiveRecord::Persistence.instance_method(:_create_record).bind(User.new).call

Rails 5.1.1 で検証
以下のようなモデルがある

# == Schema Information
#
# Table name: users
#
#  id         :integer          not null, primary key
#  token      :string(255)      not null
#  secret     :string(255)      not null
#  name       :string(255)
#  created_at :datetime         not null
#  updated_at :datetime         not null
#

class User < ActiveRecord::Base
  before_save do
    self.token  = 'foo'
    self.secret = 'bar'
  end
end

コールバックが呼び出されレコードが作成される

pry(main)> User.new.save!
  INSERT INTO `users` (`token`, `secret`, `created_at`, `updated_at`) VALUES ('foo', 'bar', '2017-06-01 04:54:17', '2017-06-01 04:54:17')
=> true

コールバックが呼び出されないため、NotNullViolation例外が発生する

pry(main)> ActiveRecord::Persistence.instance_method(:_create_record).bind(User.new).call
  INSERT INTO `users` (`token`, `secret`, `name`, `created_at`, `updated_at`) VALUES (NULL, NULL, NULL, NULL, NULL)
  => ActiveRecord::NotNullViolation: Mysql2::Error: Column 'token' cannot be null

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0