LoginSignup
6
12

More than 1 year has passed since last update.

[Rails]月間、週間、日別でランキング機能を実装(Time.current)

Last updated at Posted at 2021-07-07

先日、基本的なランキング機能の表示方法を記事にしたので、今回はランキング機能の応用編ということで、月間、週間などの期間を指定してのランキング機能を実装していきます。

先日書いた記事はこちら
[Rails]いろんなランキング表示(いいね、コメント、投稿数)

同率順位表示する記事もあげました
ランキング機能の順位を同率表示する

開発環境

ruby 2.6.3
Rails 5.2.6

前提

  • 投稿サイトを想定
  • ランキングの順位に応じて1位、2位などの順位を表示
  • ranksコントローラーのrankアクションに処理を記述
  • rank.html.erbでビューを表示

モデル名、変数名等は適宜、ご自身の開発環境に変換してお考えください。

user ユーザー
post 投稿
like いいね
comment コメント

ビュー

postとuserで渡す変数や表示させたいカラムが違うだけなので、先にやっつけておきます。
postのランキングを例にします。

1位、2位と順位を表示したいので、with_indexを使います。

views/ranks/rank.html.erb
<!--配列の1つ目から順に1位、2位と表示される-->
<% post_ranks.each.with_index(1) do |post, i| %><%= i %>位
:
<!--表示したいカラムをご自由に-->
:
<% end %>

こうするだけで、順位が表示されるようになります。

これだけ押さえておけばいい

実際のランキング表示方法の前に、これだけ押さえておけばいいポイントを説明します。
ずばり、Time.currentです!
Time.currentさえ理解できたら期間指定系のランキング機能は9割実装できたも同然です!

Time.currentとはRails独自のメソッドです。
Time.currentを使うことで、今の日時が取得できます。

ではコンソールで試してみましょう!

# rails cを実行
$rails c

# Time.currentを実行すると現在の日時が表示される
001 > Time.current
=> Wed, 07 Jul 2021 01:25:38 UTC +00:00 

これでTime.currentで現在の日時が取得できることがわかったはず。
とても便利なメソッドです。

このTime.currentを軸に今月、今週、今日とデータを取得していきます。
方法は簡単でTime.current.all_weekとすると現在の日時を含む全ての週、つまり今週という期間を指定できます。

ではコンソールで試していきます。

# 今月を表示
002 > Time.current.all_month
# すると今が2021年7月なので2021/7/1~2021/7/31までが指定される
=> Thu, 01 Jul 2021 00:00:00 UTC +00:00..Sat, 31 Jul 2021 23:59:59 UTC +00:00 

# 今週を表示
003 > Time.current.all_week
=> Mon, 05 Jul 2021 00:00:00 UTC +00:00..Sun, 11 Jul 2021 23:59:59 UTC +00:00 

# 今日を表示
004 > Time.current.all_day
=> Wed, 07 Jul 2021 00:00:00 UTC +00:00..Wed, 07 Jul 2021 23:59:59 UTC +00:00 

しっかりと対象の期間が取得できています。
たとえば、Time.current.all_weekではなく、'指定の日時'.all_weekで指定の日時を含む週を取得できたり、Time.current.ago(2.years)で今日の2年前を取得できたりもするので、色々覚えておくと便利だと思います。

時刻や日付を扱うメソッドの基本情報まとめ【Ruby】【Rails】

では以上を踏まえて実際にコードを書いていきます。

月間ランキング

月間ランキングでは、ユーザーの投稿数のランキングを例にしていきます。

controllers/ranks_controller.rb
def rank
  # 月間ランキング
  @month_user_post_ranks = User.where(id: Post.group(:user_id).where(created_at: Time.current.all_month).order('count(user_id) desc').pluck(:user_id))
end

解説します。

controllers/ranks_controller.rb
#Postモデルのuser_idが同じのまとめる
Post.group(:user_id)
#投稿が作られた日が今月のデータのみ抽出
where(created_at: Time.current.all_month)
#user_idが多い順に並べる
order('count(user_id) desc')
#user_idで取り出す
pluck(:user_id)
#Userモデルのidが一致するデータを取得する
User.where(id: )

これで、今月のユーザーの投稿数ランキングができました。

週間ランキング

週間ランキングでは、投稿のいいね数ランキングを例にしていきます。

controllers/ranks_controller.rb
def rank
  # 週間ランキング
  @week_post_like_ranks = Post.find(Like.group(:post_id).where(created_at: Time.current.all_week).order('count(post_id) desc').pluck(:post_id))
end

解説します。

controllers/ranks_controller.rb
# Postモデルから()内のデータを探してくる
Post.find()
# 次にLikeモデルのpost_idが同じものをまとめる
Like.group(:post_id)
#投稿が作られた日が今週のデータのみ抽出
where(created_at: Time.current.all_week)
# まとめたものをpost_idの多い順に並び替える
order('count(post_id) desc')
# そのままだとLikeモデルで取り出してしまうので、post_idで値を取りだす
pluck(:post_id)

これで今週の投稿のいいね数ランキングができました。

日別ランキング

日別ランキングでは、投稿のコメント数ランキングを例にしていきます。

controllers/ranks_controller.rb
def rank
  # 日別ランキング
  @today_post_comment_ranks = Post.find(Comment.group(:post_id).where(created_at: Time.current.all_day).order('count(post_id) desc').pluck(:post_id))
end

いいね数ランキングと考え方は同じで、いいねをコメントに、all_weekをall_dayに変更しただけなので、詳しい説明は割愛させていただきます。

最後に

今回はTime.currentメソッドを使って期間を指定してランキング機能を実装しました。
時間を扱えるメソッドはTime.current以外にもたくさんあって、メソッドの使い分けをしていくようです。
ぼくもまだまだ知らないメソッドだらけなので、日々勉強していきます。

最後まで見て頂きありがとうございました。

6
12
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
6
12