質問: railsのウェブアプリでデータベースの中に記事レコード(Post)があり「その中で人気がありかつ新しいものが上」という条件のscopeを定義しようと考えています。 PostはActsAsVotableでLikeボタンを押すことでLike数をvotesで集計できるようになっています。また記事ごとにアクセス数をposts.view_countに保存しています。 今は「Like数 * 10 + 記事のアクセス数の数値が高いものから(記事の作成日が1ヶ月以内)」という条件で並べています。 `scope :featuring, -> { joins(:votes).where('posts.created_at > ?', Time.now - 1.month).group('posts.id').order('(count(votes.id)*10 + posts.view_count) DESC, posts.id DESC') }` この方法ですとLike数がゼロの記事はアクセス数があってもscopeに含まれません。かつ本当に入れたい条件とは少し異なっております。 本当は 「1週間以内のLike数 * 100 + 1ヶ月以内のLike数 *10 + 記事のアクセス数の数値が高いものから(記事の作成日が2ヶ月以内)」 という条件にしたいです。 どのようにすればいいのでしょうか? できればscopeで記述したいのですが、無理ならクラス・メソッドでもかまわないと考えています。 方法はありますでしょうか? データベースはPostgreSQLです。
回答: > > 「1週間以内のLike数 * 100 + 1ヶ月以内のLike数 *10 + 記事のアクセス数の数値が高いものから(記事の作成日が2ヶ月以内)」 という条件にしたいです。 > > > たぶん、こんな感じかなーと思います。 ``` scope :featuring, -> { select("posts.*") .joins("LEFT OUTER JOIN votes ON votes.post_id = posts.id") # 実際のテーブル構造に合わせて変更してください .where('posts.created_at > ?', 2.months.ago) .group('posts.id') .order(<<-ORDER_SQL) ( SUM( CASE WHEN votes.created_at > current_timestamp + '-7 days' THEN 100 WHEN votes.created_at > current_timestamp + '-31days' THEN 10 ELSE 0 END ) + posts.view_count ) DESC, posts.id DESC ORDER_SQL } ``` 全く同じ環境で動作確認することはできないので、エラーが出た場合は適宜修正してください。