marginalia(ActiveRecord::QueryLogs) を使うと ActiveRecord::Relation#explain が空文字を返す問題
困っている人向けまとめ
- marginalia(ActiveRecord::QueryLogs) を
prepend_comment = true
の設定で使うとActiveRecord::Relation#explain
が空文字を返す問題がある - marginalia に issue が立っていて修正は既に rails/rails に取り込まれている Merge pull request #44350 from fatkodima/explain-prefix-comment · rails/rails@a32c54e · GitHub
- 2022/12/27 時点での最新版の Rails 7.0.4 ではまだ上記の修正が取り込まれていないので同様の monkey patch を当てる必要がある
marginalia を使おうとしたときにちょっと困ったことがあったのでメモ書き。
marginalia とは
marginalia gem とは、rails/rails を作った basecamp が作った gem で SQL のクエリの先頭か末尾にどの controller / action で発行されたかをクエリのコメントとして追記してくれる機能を持っている。
また、この機能は Rails 7 では ActiveRecord::QueryLogs という名前で標準の機能に取り込まれている。便利で使ってたけどメンテされてる気配がなかったので標準に取り込まれるのは嬉しい。
どんな問題が起きたのか
marginalia のデフォルトの挙動では、クエリ発行位置をクエリの末尾にコメントするようになっているが下記のように prepend_comment
option を true
にするとクエリの先頭にコメントを追記してくれるようになる。
Marginalia::Comment.prepend_comment = true
これを設定した上で ActiveRecord::Relation#explain
(e.g. User.all.explain
) を実行すると、explain 結果が空文字になってしまう問題が起きていた。
この問題は既知で、ActiveRecord::Relation#explain
は with, select, update, delete, insert のいずれかから始まるクエリでないと EXPLAIN が動作しないような実装になっているのが原因とのこと。
どう対応すればいいのか
既に rails/rails に修正は取り込まれているものの、2022/12/27 時点の Rails 最新版である 7.0.4 ではまだ反映されていないので変更に対応する monkey patch をあてる必要がある。具体的には以下。
# config/initializers/marginalia.rb # `Marginalia::Comment.prepend_comment = true` で marginalia を動かすと `ActiveRecord::Relation#explain` が空文字を返す問題の対応。 # 対応自体は https://github.com/rails/rails/commit/a32c54e49e46f08a910a993718bae78e57f3d85f で rails/rails の main branch に取り込まれている。 # 2022/12/27時点でのRails 最新バージョン(7.0.4)には取り込まれていないので、取り込まれたバージョンまで Rails が上げることができればこの monkey patch を消すことができる。 if defined?(ActiveRecord::ExplainSubscriber) && ActiveRecord::ExplainSubscriber.const_defined?(:EXPLAINED_SQLS) ActiveRecord::ExplainSubscriber::EXPLAINED_SQLS = /\A\s*(\/\*.*\*\/)?\s*(with|select|update|delete|insert)\b/i end