Rails で 指定した ID 順に取得する


やりたいこと

Rails で API サーバーとか作ってると、データを取得する際、一旦 id の配列だけを返して、
実データは別途その id の配列を送信して取得するみたいな処理をやることが多々ある。

その返却した id の配列の順序に意味がある場合、そのまま単純に ActiveRecord でデータを取得すると、
id 順 ( scope で順序を指定してるとそれ順 ) になってしまうので、それをもらった id の配列順でデータを
返却する際のやり方を調べた際のメモ。

サンプルコード

ユーザーの id の配列をアクセス日時の降順で返却するエンドポイント ( ids ) があって、
ids 順どおりに、ユーザー情報を返却するエンドポイント ( lookup ) の場合

app/users_controller.rb
class UsersController < ApplicationController

  # GET /users/ids
  def ids
    @users = User.all.order(accessced_at: :desc)
    render json: @users.pluck(:id)
  end

  # GET /users/lookup?ids[]=1&ids[]=2
  def lookup
    @users = User.where(id: params[:ids]).sort_by{|c| params[:ids].map(&:to_i).index(c.id)}
    # view が用意されている前提です。
    # app/views/users/lookup.json.jbuilder
  end
end

params[:ids].map(&:to_i)については、JSON を POST する場合 ( "ids": [1,2,3] ) などは、
prams[:ids] の中身は数値の配列 ( [1,2,3] ) なんだけど、GET パラメータでの場合は、["1","2","3"] と文字列で受け取るので、GET パラメータにも対応するために map で数値に変換してます。