ページビュー数の計測ができる「impressionist」というgemを導入します。ip_addressやsession_hashなどの情報を取得してくれるので、ユニークユーザー数が計測できます。本記事ではscaffoldでサンプルを用意して、PV数でランキングを作るところまでやってみたいと思います。
impressionist
https://github.com/charlotte-ruby/impressionist
バージョンはこちらです
1 2 3 |
ruby 2.4.0 rails 5.1.6 impressionist 1.6.1 |
準備
scaffoldでサンプルとなる環境を作ります。対象テーブルにPV数を格納する impressions_count カラムを作りintegerにしておきます。
1 |
$ rails g scaffold User name:string impressions_count:integer |
生成されたマイグレーションファイルにimpressions_count カラムに デフォルト値を 0 に設定しておきます。
db/migrate/20xxxxxxxxxx_create_users.rb
1 2 3 4 5 6 7 8 9 10 |
class CreateUsers < ActiveRecord::Migration[5.1] def change create_table :users do |t| t.string :name t.integer :impressions_count, default: 0 t.timestamps end end end |
Gemfile
1 |
gem 'impressionist' |
$ bundle install して次の generate コマンドを実行します。
1 2 3 4 5 |
$ rails g impressionist Running via Spring preloader in process 134476 invoke active_record create db/migrate/20180804231718_create_impressions_table.rb create config/initializers/impression.rb |
このコマンドだけで下記のマイグレーションファイルを生成してくれます。
db/migrate/20xxxxxxxx_create_impressions_table.rb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
class CreateImpressionsTable < ActiveRecord::Migration[5.1] def self.up create_table :impressions, :force => true do |t| t.string :impressionable_type t.integer :impressionable_id t.integer :user_id t.string :controller_name t.string :action_name t.string :view_name t.string :request_hash t.string :ip_address t.string :session_hash t.text :message t.text :referrer t.text :params t.timestamps end add_index :impressions, [:impressionable_type, :message, :impressionable_id], :name => "impressionable_type_message_index", :unique => false, :length => {:message => 255 } add_index :impressions, [:impressionable_type, :impressionable_id, :request_hash], :name => "poly_request_index", :unique => false add_index :impressions, [:impressionable_type, :impressionable_id, :ip_address], :name => "poly_ip_index", :unique => false add_index :impressions, [:impressionable_type, :impressionable_id, :session_hash], :name => "poly_session_index", :unique => false add_index :impressions, [:controller_name,:action_name,:request_hash], :name => "controlleraction_request_index", :unique => false add_index :impressions, [:controller_name,:action_name,:ip_address], :name => "controlleraction_ip_index", :unique => false add_index :impressions, [:controller_name,:action_name,:session_hash], :name => "controlleraction_session_index", :unique => false add_index :impressions, [:impressionable_type, :impressionable_id, :params], :name => "poly_params_request_index", :unique => false, :length => {:params => 255 } add_index :impressions, :user_id end def self.down drop_table :impressions end end |
1 |
$ rails db:migrate |
Models
対象となるモデルクラスに :counter_cache オプション追加します。
app/models/user.rb
1 2 3 |
class User < ApplicationRecord is_impressionable counter_cache: true end |
Controllers
app/controllers/users_controller.rb
1 2 3 4 |
def show @user = User.find(params[:id]) impressionist(@user, nil, :unique => [:session_hash]) end |
Views
app/views/users/show.html.erb
1 2 |
<strong>閲覧数:</strong> <%= @user.impressions_count %> |
ブラウザをロードしてみるとImpressionのカラムにそれぞれデータが格納され、Userのimpressions_countが + 1 になりました。
1 2 3 4 5 6 |
SQL (2.4ms) INSERT INTO "impressions" ("impressionable_type", "impressionable_id", "controller_name", "action_name", "request_hash", "ip_address", "session_hash", "referrer", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) [["impressionable_type", "User"], ["impressionable_id", 1], ["controller_name", "users"], ["action_name", "show"], ["request_hash", "7114e28ec6dfd588d90f465533947fb9cf35cec0765c4a0cbd0236669738b051"], ["ip_address", "125.195.212.31"], ["session_hash", "5ec8a96621d28b96f28e31bc15a9280e"], ["referrer", "https://xxxx.xxx.xx/users/new"], ["created_at", "2018-08-05 00:15:33.392659"], ["updated_at", "2018-08-05 00:15:33.392659"]] User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] (0.3ms) SELECT COUNT(*) FROM "impressions" WHERE "impressions"."impressionable_id" = ? AND "impressions"."impressionable_type" = ? [["impressionable_id", 1], ["impressionable_type", "User"]] SQL (0.3ms) UPDATE "users" SET "impressions_count" = COALESCE("impressions_count", 0) + 1 WHERE "users"."id" = ? [["id", 1]] (22.1ms) commit transaction (0.5ms) SELECT COUNT(DISTINCT "impressions"."request_hash") FROM "impressions" WHERE "impressions"."impressionable_id" = ? AND "impressions"."impressionable_type" = ? [["impressionable_id", 1], ["impressionable_type", "User"]] |
PVランキングを作る
次にページビュー数でランキングを作ってみます。本記事は表示用のサンプルとして、Userテーブルにseedデータを流しますが、実際にはImpressionテーブルのそれぞれのカラムにもデータが必要ですので、実際の運用には、それぞれの環境に合わせて行ってください。
db/seeds.rb
1 2 3 4 5 6 |
20.times do |no| User.create( :name => "user #{no}", :impressions_count => "#{rand(80)} " # 80までのランダムな数値を作る ) end |
1 |
$ rails db:seed |
app/controllers/users_controller.rb
1 2 3 |
def index @most_viewed = User.order('impressions_count DESC').take(10) end |
app/views/users/index.html.erb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<h1>Users</h1> <table> <thead> <tr> <th>順位</th> <th>名前</th> <th>閲覧数</th> </tr> </thead> <tbody> <% @most_viewed.each.with_index(1) do |rank, i| %> <tr> <td><%= "#{i}" %></td> <td><%= rank.name %></td> <td><%= rank.impressions_count %></td> </tr> <% end %> </tbody> </table> |
はい、これでトップ10のランキングができました!!また機会があれば週毎・月毎などの一定期間ごとのランキングの実装もしてみたいなと思います。
ご覧いただき、ありがとうございました!!