0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[未経験エンジニア]のオリジナルアプリ制作の反省6. ランキング機能の実装(簡単)

Last updated at Posted at 2021-02-09

今回書くこと

ランキング機能の実装の超簡単なやり方

環境

Ruby 2.6.5
Ruby on Rails 6.0.4.3

結論

こちらの記事を参考にデータの取得方法を工夫することで、結構簡単に実装できる。

##前提
記事にお気に入り機能を実装し、そのお気に入り数を参考してランキング機能を実装します。

テーブルとアソシエーションはこの通りです。

  • favoritesテーブル(誰かどの記事にお気に入りしたかを管理=中間テーブル)
  • usersテーブル(ユーザーの情報を管理)
  • articlesテーブル(記事の情報を管理)

the_brewers.png

※(reviewsテーブルは今回関係ありません)

記事にお気に入りが出来る(ファボできる)実装が完了していることを前提とします。

なお、お気に入り機能の作り方については、
↓こちらの↓記事が参考になります。
【Rails】お気に入り機能

方針

  1. ランキングを表示させたいアクション(7つのアクション以外でも可)内で、お気に入り数が多い順に5つレコードを取得する。
  2. ビューで表示する

それでは早速いきましょう。

1. コントローラーでデータ取得

まずは、お気に入り数が多い順にレコードを5つ取得します。

articles_controller.rb
class ArticlesController < ApplicationController

  def index
    @articles = Article.published.order(created_at: :desc).includes(:user)
    @rank_articles = Article.find(Favorite.group(:article_id).order('count(article_id) desc').limit(5).pluck(:article_id))
  end

(以下略)
end

@rank_articlesに、取得したレコードを代入しています。
少し長いので、どのようにデータを取得したのか説明を加えます。

まず、Favotitesテーブルにあるarticle_idカラムのデータの中で、重複しているものを一まとめにしています。一まとめにすると言っても、データの総数は変わりません。

Favorite.group(:article_id)       

次に、article_idの数をカウントし、その数が多い順に並べ替えます。

order('count(article_id) desc')

そして、取得するレコード数は最大で5つとします。

limit(5)

最後に、ビューで配列としてデータを扱うために、pluckメソッドで配列の形で上位5つのレコードidを取得します。

pluck(:article_id)

このデータを、ビューで利用します。

2. ビューで表示する。

ここまでで、@rank_articlesに必要な情報を入れることができました。

ここからは、ビューでの表示についてお話しします。

index.html.erb
<div class="rank">
    <h2>真似したいランキング</h2>
    <div class="rank_box">  
      <% @rank_articles.each.with_index(1) do |article, i|%>
        <div class="rank_title">
          <%= i %>位 <%= link_to article.title, article_path(article), class: "title_name"%>
        </div>
      <% end %>
    </div>
  </div>

4行目で、@rank_articlesに入っているレコードを一つずつ表示できるように処理します。
(今は、ブロック内のiは無視しても大丈夫です。)

 <% @rank_articles.each.with_index(1) do |article, i|%>

あとは、思い思いの形で表示してもらえればと思います。

補足1. each.with_index()

では、補足として、すぐ上で取り上げた表現について説明しようと思います。

ざっくりいうと、「何番目だよ!」という情報と共に、eachメソッドの処理が行われるメソッドです。()内の数は、最初の値を示しています。今回は、1位を最小の値にしたかったので、1を引数として指定しました。

そして、この何番目だよ!というデータをeachメソッドの中で利用したいので

  • 記事情報のarticle
  • 何番目を示すi(indexの頭文字)

を記述して、処理の中で利用しています。

##補足2. コントローラーの処理をモデルに移動する(ちょっと上級者向け)

articles_controller.rb
 def index
    @articles = Article.published.order(created_at: :desc).includes(:user)
    @rank_articles = Article.find(Favorite.group(:article_id).order('count(article_id) desc').limit(5).pluck(:article_id))
  end

今回は、データの取得の処理を、コントローラーに記述しました。
しかし、CoCの原則に則れば、データの取得に関する処理は、モデルが担当するべきです。

そこで、モデルにこの処理を記述します。

article.rb
def self.create_article_ranking
    Article.find(Favorite.group(:article_id).order('count(article_id) desc').limit(5).pluck(:article_id))
end

このように、クラスメソッドとしてcreate_article_rankingメソッドを定義しました。
こうすることで、

article_controlle.rb
  def index
    @articles = Article.published.order(created_at: :desc).includes(:user)
    @rank_articles = Article.create_article_ranking
  end

モデルで定義したクラスメソッドを呼び出す形で、同様の処理が可能になります。

##最後に
最後まで読んでいただき、ありがとうございます。
ソースコード、記事の書き方について「もっとこうしたほうがいいよ!」というご意見、「そこどうなっているの?」というご質問など、お待ちしております。

参考文献

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?