Ahmed Reza Siddique
Ahmed Reza Siddique

Reputation: 423

How to count page views made by users in rails?

I have a simple rails app where users can login and post updates what i want to do is add a count in each post so if someone visit a post it will get updated suppose if 100 users visited a particular post it should show the count to hundred.

I had seen impressionist but i was thinking to do this without using a gem.

i thought of creating another Modal PostView

class PageView
    belongs_to :page
    belongs_to :user
end

Upvotes: 1

Views: 7004

Answers (6)

Gunjan
Gunjan

Reputation: 21

The best solution for a large project (thousands/millions of users) is punching bag gem , go through the doc for integration : punching_bag

The major problem arises when with each request a new record is created which puts huge load on database. Gem Impressionist fails here. Punching bag too creates records but it has a rake task which comes to rescue :

Schedule a cron job to this rake task once a month/week to decrease (groups the records) the number of records without affecting the count of page views which can be found by simply - @post.hits . Here is the rake task : rake punching_bag:combine[by_hour_after,by_day_after,by_month_after,by_year_after]

Upvotes: 2

deshank
deshank

Reputation: 11

Let's think we have a blog with articles. In index page article name ,text and theme of the article will be printed.so we have to introduce a new column to index page of having no of views of an each article.

Do following changes.

app/view/articles/index.html.erb

  1. add to the table .

    <th>view</th>
    
  2. add to the data abstract part start with

    <%@articles.each_with_index do |article, index| %>  .
    
    <td><%= article.view %></td>
    

add a new column to articles database as view

  1. If you are using mysql you can manually add the column as view, make default value as 0.
  2. or run the code

    rails generate migration add_view_to_article view:int
    

app/controller/articles.controller.rb

def show
@article = Article.find(params[:id])
abc = @article.view += 1
@article.update_attribute "view", abc
end

Upvotes: 0

Md. Farhan Memon
Md. Farhan Memon

Reputation: 6121

As suggested by @Deepak, you can add a views field in the model,

def change
  add_column :page_views, :count, :integer, default: 0
end

Then, in your controller in show action,

def show
  #your show logic
  if (user = current_user).present?
    current_user.page_views.where(page_id: @page.id).first_or_initialize.increment!(:count)
  end
end

This makes sense because whenever the page is visited, counter should be incremented by 1..and your post request is saved..

Upvotes: 0

Deepak Mahakale
Deepak Mahakale

Reputation: 23661

You can add a views field in the model and increment it on each page view

def change
  add_column :page_views, :count, :integer, default: 0
end

and

# app/controllers/pages_controller.rb
def increment
  @pageview = PageView.where(user_id: current_user, page_id: params[:id]).first_or_create
  @pageview.increment!(:count)
end

And just add a route in pages controller

# routes.rb
resources :pages do 
  post :increment 
end

Upvotes: 2

everyman
everyman

Reputation: 3407

Since it wasn't mentioned yet, you should also checkout https://github.com/charlotte-ruby/impressionist which makes view tracking very easy and flexible.

This is the data which is saved with each view and could get handy later:

t.string   "impressionable_type"  # model type: Widget
t.integer  "impressionable_id"    # model instance ID: @widget.id
t.integer  "user_id"              # automatically logs @current_user.id
t.string   "controller_name"      # logs the controller name
t.string   "action_name"          # logs the action_name
t.string   "view_name"            # TODO: log individual views (as well as partials and nested partials)
t.string   "request_hash"         # unique ID per request, in case you want to log multiple impressions and group them
t.string   "session_hash"         # logs the rails session
t.string   "ip_address"           # request.remote_ip
t.text     "params"               # request.params, except action name, controller name and resource id
t.string   "referrer"             # request.referer
t.string   "message"              # custom message you can add

So for example you could query something like: "Give me all views for a specific user grouped by Model and Sessions." and stuff like this.

Upvotes: 2

zauzaj
zauzaj

Reputation: 1226

Basically you can add additional field to post, like visit_counter:

class Post
  def increase_visit
    visit_counter+=1
    save!
  end
end

Then in posts_controller#show, you can do some increment:

class PostsController
  def show
  ............
  @post.increase_visit
  end
end

That means, every time you render posts#show view someone actually visited particular post so you should increment number of visits.

In case you need more flexible and advance approach ( to count visits per user, or per days etc ) you can define separate model VisitCounter which would be associated with your Post model.

Regards

Upvotes: 3

Related Questions