Rails の ActiveRecord の update で validate が実行されるかを見てみる
Ruby Ruby on Rails
Published: 2019-07-17

やったこと

Rails の ActiveRecord で update を実行するときに、 validate が呼び出されるのかを検証してみます。

確認環境

$ ruby --version
ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-darwin17]

$ rails --version
Rails 5.2.3

調査

validate が呼び出されているかを調べる

app/models/task.rb

class Task < ApplicationRecord
  validate :hoge

  def hoge
    logger.debug("custom validate: #{__method__}")
  end
end

実行結果

$ rails c
Running via Spring preloader in process 29317
Loading development environment (Rails 5.2.3)
irb(main):001:0> Task.all
  Task Load (1.9ms)  SELECT  "tasks".* FROM "tasks" LIMIT ?  [["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<Task id: 4, created_at: "2019-06-12 12:50:53", updated_at: "2019-06-12 12:50:53", name: "name1">, #<Task id: 5, created_at: "2019-06-12 12:52:31", updated_at: "2019-06-12 12:52:31", name: "name1">]>
irb(main):002:0> t = Task.find(4)
  Task Load (0.2ms)  SELECT  "tasks".* FROM "tasks" WHERE "tasks"."id" = ? LIMIT ?  [["id", 4], ["LIMIT", 1]]
=> #<Task id: 4, created_at: "2019-06-12 12:50:53", updated_at: "2019-06-12 12:50:53", name: "name1">
irb(main):003:0> t.update(name: "name22")
   (0.1ms)  begin transaction
custom validate: hoge
  Task Update (0.5ms)  UPDATE "tasks" SET "updated_at" = ?, "name" = ? WHERE "tasks"."id" = ?  [["updated_at", "2019-07-14 15:51:29.933901"], ["name", "name22"], ["id", 4]]
   (3.5ms)  commit transaction
=> true

update が実行されると validate も実行されていることが分かります。

validate の unique 制約が働くのか調べる

app/models/task.rb

class Task < ApplicationRecord
  validates :name , uniqueness: true, presence: true
  validate :hoge

  def hoge
    logger.debug("custom validate: #{__method__}")
  end
end

実行結果

$ rails c
Running via Spring preloader in process 30205
Loading development environment (Rails 5.2.3)
irb(main):001:0> Task.all
  Task Load (1.4ms)  SELECT  "tasks".* FROM "tasks" LIMIT ?  [["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<Task id: 4, created_at: "2019-06-12 12:50:53", updated_at: "2019-07-14 16:01:58", name: "name2">, #<Task id: 5, created_at: "2019-06-12 12:52:31", updated_at: "2019-06-12 12:52:31", name: "name1">]>
irb(main):002:0> task = Task.find(4)
  Task Load (0.2ms)  SELECT  "tasks".* FROM "tasks" WHERE "tasks"."id" = ? LIMIT ?  [["id", 4], ["LIMIT", 1]]
=> #<Task id: 4, created_at: "2019-06-12 12:50:53", updated_at: "2019-07-14 16:01:58", name: "name2">
irb(main):003:0> task.update(name: "name1")
   (0.1ms)  begin transaction
  Task Exists (0.2ms)  SELECT  1 AS one FROM "tasks" WHERE "tasks"."name" = ? AND "tasks"."id" != ? LIMIT ?  [["name", "name1"], ["id", 4], ["LIMIT", 1]]
custom validate: hoge
   (0.1ms)  rollback transaction
=> false

unique 制約のバリデーションが効いていることが分かります。

参考