11982


idsはArrayで中にPostモデルの取り出したいidが先頭から順番に入っています。

[code]

    ids = [23, 12, 34, 45, 9]
    
[/code]

これとwhere句を使ってPostを取り出すことはできていますが、順番が意図している順序になりません。

[code]

    > p = Post.where(id: ids)
    > p
    => [#<Post id: 9, name: 'test_9'>,
    #<Post id: 12, name: 'test_12'>,
    #<Post id: 23, name: 'test_23'>,
    #<Post id: 34, name: 'test_34'>,
    
[/code]

これをidsの配列に格納した要素と同じ順番で取り出すにはどうすればいいのでしょうか？  
つまり結果のPostを[23, 12, 34, 45, 9]の順に得たいと考えています。

[code]

    Post.where(id: ids).sort_by{|o| ids.index(o.id)}
    
[/code]

を考えましたが、この結果はArrayクラスで返ってくるため使えませんでした。  
Postモデルで指定したscopeなどをこの後で利用するため、結果はPost::ActiveRecord_Relationで得る必要があります。


CC BY-SA 3.0
2015-07-02T14:57:28.843
11972
2015-07-03T06:18:33.307
9202
question
ruby-on-rails ruby rails-activerecord
rails のwhere句の結果を指定の順番で取り出す方法は？


こちらの回答が参考になるかもしれません。

<https://stackoverflow.com/a/26777669/1058763>

## MySQLの場合 => FIELD関数を使う

[code]

    > ids = [11,31,29]
    => [11, 31, 29]
    > User.where(id: ids).order("field(id, #{ids.join(',')})")
    
[/code]

こちらも参考になりそうです。

[Rails - MySQL+ActiveRecordで、与えられた配列順にorderしたい時 -
Qiita](http://qiita.com/chezou/items/8c0481044c954c4bca3b)

## PostgreSQLの場合 => CASE WHENを動的に生成してorderに渡す

[code]

    def self.order_by_ids(ids)
      order_by = ["case"]
      ids.each_with_index.map do |id, index|
        order_by << "WHEN id='#{id}' THEN #{index}"
      end
      order_by << "end"
      order(order_by.join(" "))
    end
    
    User.where(:id => [3,2,1]).order_by_ids([3,2,1]).map(&:id) 
    #=> [3,2,1]
    
[/code]

## 追記：[order_as_specified](https://github.com/panorama-ed/order_as_specified)
gemを使う

こちらの回答の中に「gemを作ったよ」と回答している人がいました。

<https://stackoverflow.com/a/29039262/1058763>

[code]

    # 使い方
    MyModel.where(id: ids).order_as_specified(id: ids)
    
    # 生成されるORDER BY句
    ... ORDER BY ID='5' DESC, ID='1' DESC, ID='17' DESC, ID='84'  DESC
    
[/code]

こういうSQLでも順番を指定できるとは知りませんでした。  
こちらもご参考までに。


CC BY-SA 3.0
2015-07-03T02:10:51.157
11982
2015-07-03T06:18:33.307
2017-05-23T12:38:55.307
-1
85
11972
answer