LoginSignup
4
9

More than 1 year has passed since last update.

【rails】PV数の実装(impressionist)

Last updated at Posted at 2021-05-11

実装すること

  • gem impressionistを使用して、投稿ページにPV(ページビュー)を設置します。
  • 同じユーザーがPV数を稼ぐ、増やせないように同じセッションはカウントしないようにします。

impressionist: https://github.com/charlotte-ruby/impressionist
こちらのgithubを参考に実装していきます。

完成形

目のアイコンがPV数を表示しており、
投稿詳細に行くと数字がカウントされています。

gif.gif

前提

下記の機能実装済み。
・devise(今回は、memberモデル)
・投稿機能(今回は、questionモデル)

schema.rb
ActiveRecord::Schema.define(version: 2021_05_05_122222) do

  create_table "members", force: :cascade do |t|
    t.string "email", default: "", null: false
    t.string "encrypted_password", default: "", null: false
    t.datetime "remember_created_at"
    t.string "name", default: "", null: false
    t.text "introduction"
    t.string "image_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["email"], name: "index_members_on_email", unique: true"index_members_on_reset_password_token", unique: true
  end

  create_table "questions", force: :cascade do |t|
    t.integer "member_id", null: false
    t.string "title", default: "", null: false
    t.text "content", null: false
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["member_id"], name: "index_questions_on_member_id"
  end
end

手順

①gem"impressionist"の導入
②modelへの記載
③controllerへの記載
④viewへの記載

実装

1. impressionistのインストール

railsのバージョンに注意。(6と5以下で異なる)
私は5なので、下記を記載。

Gemfile
#rails 5 or lower
gem 'impressionist', '~>1.6.1'

インストールします。

terminal
bundle install

impressionistのマイグレーションファイルを作成します。

terminal
rails g impressionist

下記が自動的に作成されます。
*user_idとありますが、ここは特にいじる必要はありません。
 私はuserではなく、memberを使用していたのでmember_idに修正したところエラーが出ました。 
 私自身が作成したmemberモデルを表すidではなかったです。

create_impressions_table.rb
class CreateImpressionsTable < ActiveRecord::Migration[5.2]
  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

dbに反映させましょう。

terminal
rails db:migrate

2. modelへの記載

models/question.rb
class Question < ApplicationRecord
  is_impressionable

  belongs_to :member

  validates :title, presence: true
  validates :title, length: { minimum: 5, maximum: 50 }, allow_blank: true
  validates :content, presence: true
  validates :content, length: { minimum: 20 }, allow_blank: true

end

下記を一番上に追加しています。

is_impressionable

or

is_impressionable :counter_cache => true

これを追加することで、questionモデルでimpresionistを使う事ができます。

3. controllerへの記載

questions_controller.rb
class Public::QuestionsController < ApplicationController
  impressionist :actions => [:show]

  def show
    @member = current_member
    @question = Question.find(params[:id])
    impressionist(@question, nil, unique: [:session_hash.to_s])
  end

それぞれ説明します。

impressionist :actions => [:show]

⇨ PV数を計測したいので、アクションを指定します。

 ・投稿詳細(questions#show)で計測したい。
 ・[ ]内は、計測したいアクションを記載。

impressionist(@question, nil, unique: [:session_hash.to_s])

⇨ showアクション内にも記載します。

 ・@questionを計測する対象として設定します。
  今回は、投稿詳細なので@question。showにある変数を入れましょう。

 ・uniqueでは、どの値で計測するかを書きましょう。今回は、sessionで計測したいので、
  先ほど作成した、マイグレーションファイルのカラム名を書きましょう。(参照: t.string :session_hash)

4.viewへの記載

*わかりやすくするために余計な箇所は省いてあります。

questions/show.html.erb
<div class="container">
 <div class= "row">
   <div class="col-md-3 pt-5">
   <i class="fas fa-eye"> 
    <%= @question.impressionist_count(:filter=>:session_hash) %> 
   </i>
   </div>
 </div>
</div>

ここで計測(いわゆるcount)したいので、下記を記載します。

<%= @question.impressionist_count(:filter=>:session_hash) %>

・ impressionist_countで計測。
・ (:filter=>:session_hash)でフィルターをかけ、どれで計測するか設定。
  今回は、sessionで計測なので、記載の通り。

これで問題なく計測できるかと思います。
もし、エラーや上手く動かない。などあればコメント頂けたらと思います。



以上です。

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