概要
ActiveRecordを継承したモデルで属性値を変えずにupdateメソッドを実行しても、更新するSQL自体実行しない。
更新日付のupdate_atも更新されない。
モデルの値を変えない
というのは明示的に属性値を変える前と同じ値を代入
しても同様に更新するSQL自体実行しない。
前提条件
Rails: 5.2
Ruby: 2.5.1
本題
サンプルのユーザテーブルの定義
create_table :users do |t|
t.string :name
t.timestamps
end
ユーザモデルの定義
class User < ApplicationRecord
end
サンプル用に適当なUserモデルを作成しupdated_atを表示する
User.first.updated_at
=> Tue, 29 Jan 2019 03:56:08 UTC +00:00
User.first.updated_at.to_i
=> 1548734168
name属性を、Userモデルに元々入っていた値でupdateする。
後述する変更した場合と比べると、UPDATE文のSQLが実行されないことがわかる
実行結果のupdated_atが、updateメソッド実行前のupdate_atと同じ1548734168で有ることがわかる
> User.first.update!(name: User.first.name)
User Load (0.2ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? [["LIMIT", 1]]
User Load (0.2ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? [["LIMIT", 1]]
(0.1ms) begin transaction
(0.0ms) commit transaction
=> true
irb(main):008:0> User.first.updated_at.to_i
=> 1548734168
検証ついでにname属性の値を変更すると、UPDATE文のSQLが実行され、updated_atの値が更新されることがわかる
> User.first.update!(name: User.first.name + "1")
User Load (0.2ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? [["LIMIT", 1]]
User Load (0.2ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? [["LIMIT", 1]]
(0.1ms) begin transaction
User Update (1.3ms) UPDATE "users" SET "name" = ?, "updated_at" = ? WHERE "users"."id" = ? [["name", "テスト1"], ["updated_at", "2019-02-01 08:27:12.468565"], ["id", 2]]
(2.9ms) commit transaction
=> true
> User.first.updated_at.to_i
User Load (0.3ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? [["LIMIT", 1]]
=> 1549009632