クラスの拡張時にsuperでブロックを渡す

こんな感じの短いブロックを使った処理を毎回書いてるなって時ないでしょうか。

uniq_arr = arr.uniq{ |item| item[:name] }

メソッドにしても同じようなことはできるのですが、

def name_uniq arr
  arr.uniq{ |item| item[:name] }
end

name_uniq arr

メソッドに分離すると順番が逆になってしまったりするんですよね。

そんな時はこんな拡張はどうでしょう。Procを引数として渡してsuperいるのでブロックが渡せます。

class ExtendedArray < Array
  def uniq
    super do |item|
      item[:name]
    end
  end
end

arr = ExtendedArray.new

arr << {usr_id: 1, name: "Woods"}
arr << {usr_id: 2, name: "Rhodes"}
arr << {usr_id: 3, name: "Woods"}

p arr
# [{:usr_id=>1, :name=>"Woods"}, {:usr_id=>2, :name=>"Rhodes"}, {:usr_id=>3, :name=>"Woods"}]

p arr.uniq
# [{:usr_id=>1, :name=>"Woods"}, {:usr_id=>2, :name=>"Rhodes"}]

キーだけ変える可能性がある場合は、一旦元のメソッドを退避させてから呼び出します。

class ExtendedArray < Array
  alias_method :origin_uniq, :uniq
  def uniq(key)
    origin_uniq do |item|
      item[key]
    end
  end
end

arr = ExtendedArray.new

arr << {user_id: 1, name: "Woods"}
arr << {user_id: 1, name: "Rhodes"}
arr << {user_id: 3, name: "Woods"}

p arr
# [{:user_id=>1, :name=>"Woods"}, {:user_id=>1, :name=>"Rhodes"}, {:user_id=>3, :name=>"Woods"}]

p arr.uniq(:name)
# [{:user_id=>1, :name=>"Woods"}, {:user_id=>1, :name=>"Rhodes"}]

p arr.uniq(:user_id)
# [{:user_id=>1, :name=>"Woods"}, {:user_id=>3, :name=>"Woods"}]