Railsで、has_manyなどで関連している別テーブルのカラムの値が特定の値のものを上位に持って来ようと色々試して失敗したんですが、最終的にこのやり方でうまくいきました。ユースケースとしては、ブログ記事の一覧を取得しようとした時に、特定のユーザーからのコメントがある記事を上位に表示したい場合などが考えられます(そもそも、そんな状況ないとか言わないで・・)。
class Post < ActiveRecord::Base
has_many :comments
end
class Comment < ActiveRecord::Base
belongs_to :post
belongs_to :user
end
class User < ActiveRecord::Base
has_many :comments
end
というようなモデルを考えた時に、Post
モデルに次のようなスコープを作ります。
post.rb
scope :prioritize_users_comment, lambda { |user_id|
includes(:comments).order("
case
when comments.user_id = :user_id then 1
else 0
end desc
", user_id: user_id).references(:comments)
}
すると、
Post.prioritize_users_comment(7)
とすれば、id:7のユーザーのコメントがついた記事が上位にソートされて返ってきます。ポイントはSQLのCASE
式を使うこと、includes
,references
を使ってLEFT OUTER JOIN
することですね。
もっと良いやり方があったら教えて下さい〜