order、つけ忘れがちですよね。環境が変わると思ってた順番に出なかったりします。
更に厄介なのは、つけ忘れてもなんとなく正しい順番で動いているときで、何かのタイミングで思った順ではなくなってしまうことがあります。というかありました。
多分僕の場合はDBのマイナーアップグレードの影響のように見えました。詳細は追っていないですが、確かに一部でOrder指定が漏れていたので順番が変わってしまったのです。
そういう事態に開発中に気がつけるようにするため、must_be_ordered
というgemを作りました。勤めてる会社の社内ハッカソンが8/31にあったので、ちょうどいいネタとばかりにこれを作りました。
gemはこちらにございます。
現時点での使い方を紹介します(インターフェースはそのうち変わっている気がする)。
Rails、というかActiveRecordで使うのでGemfileにこのgemを追加します。
# Gemfile
gem 'must_be_ordered'
んで、bundle install
します。
そしたら今度はconfig/initializers/
以下に1個ファイルを作って↓のように書きます。
# config/initializers/must_be_ordered.rb
MustBeOrdered.enabled = !Rails.env.production?
# ↓はお好みでON/OFF
MustBeOrdered.raise = true
MustBeOrdered.must_be_ordered_logger = true
MustBeOrdered.rails_logger = true
あとは使いたいクラスの先頭でDSLっぽくmust_be_ordered
を呼び出せばOK。
class Item < ApplicationRecord
must_be_ordered
end
全モデルを監視したいなら、ApplicationRecord
につけると良さそうです。
これでorderのない状態でRelationでクエリが実行されるとエラーなりログなりが出る状態になりました。
試しに既存プロジェクトで上記のような設定を有効にしてrails console
で試してみました。
対象クラスはUser
です。まずはOrder無し。こちらはエラーとなります。
[10] pry(main)> User.where("id > ?", 10)
MustBeOrdered order not applied User:
bin/rails:4:in `require'
bin/rails:4:in `<main>'
続いてOrder有り。エラーは飛びませんね。
[11] pry(main)> User.where("id > ?", 10).order("id")
User Load (10.7ms) SELECT "users".* FROM "users" WHERE (id > 10) ORDER BY id
[12] pry(main)>
エラーではアグレッシブすぎるというのであればログだけにして使うと良いです。
仕事のプロジェクトにも入れるぞー。