ActiveRecordのorderメソッドに引数を複数渡す場合について

ActiveRecordのorderメソッドに引数を複数渡せることは有名だと思います。
ですが「複数の値を渡すとどのようにソートされるのか」について具体的に言及している記事が少ないように感じたので、簡単な例を挙げてまとめてみたいと思います。
(自分の検索能力が低いだけかも知れませんが)

検証準備

複数のカラムを持つUserテーブルを定義して、以下のレコードを格納します。

id name gender role
1 Alice 2 1
2 Bob 1 1
3 Carol 2 2
4 Dave 1 2


カラムはそれぞれ、名前、性別、ロールです。それぞれ単なる検証用の値なので、深い意味はありません。

そしてUserモデルの中に、以下のメソッドを定義します。

class User < ApplicationRecord
  def print
    puts "id:#{id} name:#{name} gender:#{gender} role:#{role}"
  end
end


これで準備は完了です。

引数が一つの場合

まずは簡単な例からやってみましょう。nameをorderの引数にする場合です。

irb(main):001:0> users = User.all.order(:name)
irb(main):002:0> users.each {|user| user.print}
id:1 name:Alice gender:2 role:1
id:2 name:Bob gender:1 role:1
id:3 name:Carol gender:2 role:2
id:4 name:Dave gender:1 role:2


ユーザーの名前はアルファベット順になっているので、このような結果になります。genderやroleを引数にした場合は以下のとおりです。

irb(main):001:0> users = User.all.order(:gender)
irb(main):002:0> users.each {|user| user.print}
id:2 name:Bob gender:1 role:1
id:4 name:Dave gender:1 role:2
id:1 name:Alice gender:2 role:1
id:3 name:Carol gender:2 role:2

irb(main):003:0> users = User.all.order(:role)
irb(main):004:0> users.each {|user| user.print}
id:1 name:Alice gender:2 role:1
id:2 name:Bob gender:1 role:1
id:3 name:Carol gender:2 role:2
id:4 name:Dave gender:1 role:2


gender, roleの場合、それぞれが1, 2という順で並びます。

引数が2つの場合

ここからが本題です。引数が複数渡された場合、どのような順序になるのでしょう。

# 性別昇順、ロール昇順
irb(main):001:0> users = User.all.order(:gender, role: :asc)
irb(main):002:0> users.each {|user| user.print}
id:2 name:Bob gender:1 role:1
id:4 name:Dave gender:1 role:2
id:1 name:Alice gender:2 role:1
id:3 name:Carol gender:2 role:2

# 性別昇順、ロール降順
irb(main):003:0> users = User.all.order(:gender, role: :desc)
irb(main):004:0> users.each {|user| user.print}
id:4 name:Dave gender:1 role:2
id:2 name:Bob gender:1 role:1
id:3 name:Carol gender:2 role:2
id:1 name:Alice gender:2 role:1


最初に渡される引数は性別で、後に渡される引数はロールです。
その場合、性別がまず優先してソートされ、1が先、2が後という順序になります。
その後、第二引数として渡されたロールの順序によってソートされているのがわかるでしょうか。

つまりorderメソッドに引数を複数渡す場合、「先に渡した引数が優先条件としてソートされ、その後、後に渡した引数を条件としてソートされる」ということになります。

もうひとつの例として、ロール、性別の順で引数を渡した場合を見てみます。

# ロール降順、性別昇順
irb(main):001:0> users = User.all.order(role: :desc, gender: :asc)
irb(main):002:0> users.each {|user| user.print}
id:4 name:Dave gender:1 role:2
id:3 name:Carol gender:2 role:2
id:2 name:Bob gender:1 role:1
id:1 name:Alice gender:2 role:1

# ロール降順、性別降順
irb(main):001:0> users = User.all.order(role: :desc, gender: :desc)
irb(main):002:0> users.each {|user| user.print}
id:3 name:Carol gender:2 role:2
id:4 name:Dave gender:1 role:2
id:1 name:Alice gender:2 role:1
id:2 name:Bob gender:1 role:1


第一引数がロールの降順なので、2→1としてソートされた後、性別でソートされていますね。

以上、複数の引数でorderした場合の簡単な例でした。