📌
ActiveRecordのupdateの処理追跡班
「ActiveRecordのupdate処理って、update前と同じ値にupdateする時って、SQL発行されるのかな〜」という疑問から、update処理を追ってみました。
以下のようなパターンです。
tag = Tag.find(1)
Tag Load (0.9ms) SELECT "tags".* FROM "tags" WHERE "tags"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
# => #<Tag:0x0000ffff8cbe4240 id: 1, name: "Romance">
tag = Tag.find(1).update(name: "Romance") # 全く同じ名前に更新する
AIに聞いたらすぐ答え返ってきたのですが、嘘つかれたので、たまには自分でコードリーディングをしてみます。
ちなみに、、GTPとGeminiどちらかが嘘つきです。
- GPT-4.5(o4)
はい、ActiveRecord の update は「同じ値」であっても基本的には SQL を発行します(=UPDATE文が実行されます)。
- Gemini 2.5 Flash
いいえ、ActiveRecord の update メソッド(および update_attributes)は、update の前と同じ値に更新しようとしても、通常は SQL (UPDATE クエリ) は発行されません
ActiveRecord::Base
-
各モデルクラス <
ApplicationRecord
<ActiveRecord::Base
ActiveRecord::Base
によって、各モデルクラスをActiveRecordたらしめています。
各テーブルのデータをオブジェクトとして扱うことができるようになります。 -
しかし、このクラスにはupdateメソッドはありません。includeしている別moduleを探します〜
ActiveRecord::Persistence
-
ActiveRecord::Base
がincludeしているmodule
永続化関係(saveとかupdateとか)の機能を持つモジュールのようです(多分) - update発見activerecord/lib/active_record/persistence.rb, line 563
def update(attributes) # The following transaction covers any possible database side-effects of the # attributes assignment. For example, setting the IDs of a child collection. with_transaction_returning_status do assign_attributes(attributes) save end end
- 引用: https://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-update
- 属性を設定して、保存しているだけに見える、、
ActiveRecord::AttributeMethods::Dirty
-
ActiveRecord::Base
がincludeするActiveRecord::AttributeMethods
がincludeしているmodule -
Active Record modelsの変更をトラッキングする機能を持つ
dirty(汚れ) = データベースのデータからの変更 -
属性設定時に発火するらしい(追えてない...)
- save時にDirty が登録されている属性のみ UPDATE 対象になる -> 値に変化がある場合のみ、UPDATEのSQLが発行される
結論
- ActiveRecordのupdate処理って、update前と同じ値にupdateする時って、SQL発行されない
- Geminiは真実を語っていた。chatGPTには嘘つかれた。
- 検証
TODO: あとで記載
まとめ
- 結局コードリーディングにはAI頼りました。includeされているmoduleとかを自分で追うのが辛すぎた
- しかし、安直にAIを信じない方がいい。信頼できるか確認しながら対話するのがよい。
Discussion