default_order の重複カラムを除去して ORDER BY を簡潔化
default_order が同じカラムを複数渡されたときに ORDER BY 句に重複が生じていた問題を解消し、order と regroup と同様に重複カラムを自動で削除するようになりました。これにより生成される SQL がシンプルになり、余計なソート処理が回避されます。
背景
default_order が重複カラムをそのまま出力していた のは、引数配列をそのまま保持していたためです。例えば User.default_order(:name, :name) を実行すると、ORDER BY "users"."name" ASC, "users"."name" ASC という二重の並び替えが生成されました。この重複は結果セットに影響しないものの、SQL が冗長になるだけでなく、デバッグ時に不要なノイズとなります。
order と regroup では既に重複除去が行われている ことから、default_order だけが例外的な振る舞いをしていた点が統一感を欠く原因となっていました。PR の目的は、この不一致を解消し、ActiveRecord の並び替え系メソッド全体で同一の挙動を提供することです。
技術的な変更
activerecord/lib/active_record/relation/query_methods.rb の default_order! 内で引数配列をそのまま保存していた箇所に、args.uniq! を追加しました。これにより、default_order の内部実装は以下のように変化します。
変更前:
self.default_order_values = args
変更後:
args.uniq!
self.default_order_values = args
args.uniq! が呼び出されることで、同一カラムが複数回渡されても配列は一意化され、default_order_values には重複のないリストだけが格納されます。結果として Topic.default_order("id desc", "id desc") のテストは ["id desc"] という期待通りの配列を返すようになりました。
設計判断
重複除去はメソッド内部で行う 方針が採用されました。外部から重複チェックを要求する代わりに、default_order! が受け取った引数を即座に正規化することで、呼び出し側は変更を意識せずに同一インタフェースを利用できます。これは 後方互換性を保ちつつ 既存の API を拡張する安全なアプローチです。
args.uniq! のみの追加 という最小限の変更にとどめた点も重要です。余計なロジックや新しいメソッドを導入しなかったため、パフォーマンスへの影響は測定不能なほど小さく、既存のテストスイートへの回帰リスクも低減されています。
まとめ
default_order が重複カラムを自動で除去するようになり、SQL の ORDER BY が簡潔化されました。order と regroup と振る舞いを揃えることで、ActiveRecord の並び替え系メソッド全体に一貫性がもたらされ、開発者は余計な重複指定を意識せずに済むようになっています。