複数のキーでソート

メモ

class User
  attr_reader :id, :name
  def initialize(id, name)
    @id, @name = id, name
  end
end

class Array

  def custom_sort(orders)
    self.sort do |a, b|
      Array.compare(a, b, orders)
    end
  end
  
  def self.compare(a, b, orders)
    orders.each_with_index do |o, i|
      key = o.class == Symbol ? o : o.keys.first
      if a.send(key) == b.send(key) && orders.size > 1
        return Array.compare(a, b, orders[(i + 1)..(orders.size - 1)])
      else
        a, b = b, a if o.class == Hash && o.values.first == :desc
        return a.send(key) <=> b.send(key)
      end
    end
  end
  
end

arr = []

arr << User.new(2, "foo")
arr << User.new(1, "foo")
arr << User.new(3, "bar")
arr << User.new(3, "foo")
arr << User.new(1, "bar")

require 'pp'
pp arr.custom_sort([:name, :id])
# => 
[#<User:0x2b54864 @id=1, @name="bar">,
 #<User:0x2b54904 @id=3, @name="bar">,
 #<User:0x2b54954 @id=1, @name="foo">,
 #<User:0x2b54990 @id=2, @name="foo">,
 #<User:0x2b548b4 @id=3, @name="foo">]