4
9

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 5 years have passed since last update.

Redisでランキングを実装

Last updated at Posted at 2019-01-27

初めに

Redisでランキングを実装してみました。

rank.png

こちらのサイトを参考にしました。
RailsでRedisを使うメモ ランキングつくったり
http://o.inchiki.jp/obbr/307

設定

デザインはbootstrap
ダミーデータ作成にfakerをつかいました。

あとredisを使うので

gemfileに

gem 'redis'
gem 'bootstrap'
gem 'jquery-rails'
gem 'popper_js'
gem 'tether-rails'
gem 'faker'

こんな感じで書いてbundle installしました。

userモデルを作成しました。

bootstrapの設定fakerでのダミーデータ作成は省略

実装

users_controllerを

users_controller.rb
class UsersController < ApplicationController
  def index
    @ranking_users_data = (REDIS.zrevrangebyscore "users", 10, 0, withscores: true)
  end

  def add_score
    user = User.find params[:id]
    REDIS.zincrby "users", 1, user.id
  end 
end

こんな感じにしました。

REDISに関しては

config/initializers以下にredis.rbを作成して中身に

redis.rb
REDIS = Redis.new(host: "localhost", port: 6379)

と書くことで使えます。

REDIS.zincrby "users", 1, user.id

みたいに書いているところでスコアのカウントをしています。

usersがスコアを計算する大きなまとまりの名前でusersでなくても良いのですが今回はusersと名前を付けています。

そのあとの1が追加する数です

user.idごとにスコアがカウントされていきます。

集められたスコアをソートされた状態で出力するには

REDIS.zrevrangebyscore "users", "+inf", 0, withscores: true

このコードです。
スコアが+inf(最大?)から0まで表示することになっています。

例えばスコアが0から10まで表示したい場合は

REDIS.zrevrangebyscore "users", 10, 0, withscores: true

あくまでスコアなので0から10番目を表示というわけではありません。

自分の場合これだけだと登録されたばかりのuserはredisのusersのランキングの中に入らないので

REDIS.zrevrangebyscore "users", 10, 0, withscores: true

これで表示されませんでした。

なのでuserが作成されたときに1スコアをたして表示されるようにしました。

models/user.rb

user.rb

class User < ApplicationRecord
    after_create{ REDIS.zincrby "users", 1, self.id}
end

routesは

Rails.application.routes.draw do
  get 'users/index'
  post 'users/add_score/:id', to: 'users#add_score'
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end

このようにして

viewsは

index.html.erb
<br>
<br>
<br>
<br>
<br>
<div class="container">
    <table class="table table-dark">
        <thead>
            <tr>
            <th scope="col">Ranking</th>
            <th scope="col">Name</th>
            <th scope="col">Count</th>
            <th scope="col">Like Button</th>
            </tr>
        </thead>
        <tbody>
            <% @ranking_users_data.each_with_index do |rank_data,index| %>
                <tr>
                    <th scope="row"><%= index + 1 %></th>
                    <td><%= user_name(rank_data[0]) %></td>
                    <td class="count"><%= rank_data[1].to_i %></td>
                    <td>
                        <%= button_to "/users/add_score/#{rank_data[0]}", class: "like-btn", id: "addBtn",  remote: true do %>
                            <i class="fas fa-heart" style="font-size: 15px;" data-count="<%= index  %>"></i>
                        <% end %>

                    </td>
                </tr>
            <% end %>
        </tbody>
    </table>
</div>


<script>
var allBtn = document.getElementsByClassName('like-btn')
var allCount = document.getElementsByClassName('count')
var btnLength = allBtn.length 
var addLikeCount = function(i) {
    allCount[i].innerHTML = parseInt(allCount[i].innerHTML) + 1
}
for(var i = 0; i < btnLength; i++ ) {
    allBtn[i].addEventListener('click', function(a) {
        let dataCount = this.getElementsByClassName('fas')[0].dataset.count
        addLikeCount(dataCount);
    });
}

</script>

例のごとく自分はjavascriptをerbの中に書いています。

とりあえず見た目はこんな感じになると思います。

rank.png

fontawesomeを使っているので

layoutsのheadの中に

<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css">

を書いて

assets/stylesheets/application.scssに

@import '/*';
@import 'bootstrap';
@import 'tether';

body 
{
    background: #95a5a6;
}

.like-btn
{
    transition: all 0.2s;
    border: none !important;
}

.like-btn:hover
{
    background: rgb(224, 0, 37) !important;
    color: white !important;
    border: none !important;
}

こんな感じにしてあると見た目は同じになると思います。

これでクリックされるたびにスコアが追加されていきます。

ちなみに

redisに追加されているデータをみたい場合は

rails cで

REDIS.keys

とすれば登録されているkeyが出て

REDIS.zrevrangebyscore "users", "+inf", 0, withscores: true

と入力すればuser.idとスコアが二次配列の形で表示されると思います。

おわり:sunny:

4
9
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
4
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?