simple hit counter for page views in rails

后端 未结 1 815
独厮守ぢ
独厮守ぢ 2020-11-28 02:17

I\'ve found several solutions for this problem, for example railstat from this post:

Page views in Rails

I have a bunch of articles and reviews which I would

相关标签:
1条回答
  • 2020-11-28 02:28

    UPDATE

    The code in this answer was used as a basis for http://github.com/charlotte-ruby/impressionist Try it out


    It would probably take you less time to code this into your app then it would to pull the data from Analytics using their API. This data would most likely be more accurate and you would not have to rely an an external dependancy.. also you would have the stats in realtime instead of waiting 12 hours on Analytics data. request.remote_ip works pretty well. Here is a solution using polymorphism. Please note that this code is untested, but it should be close.

    Create a new model/migration to store your page views (impressions):

    class Impressions < ActiveRecord::Base
      belongs_to :impressionable, :polymorphic=>true 
    end
    
    class CreateImpressionsTable < ActiveRecord::Migration
      def self.up
        create_table :impressions, :force => true do |t|
          t.string :impressionable_type
          t.integer :impressionable_id
          t.integer :user_id
          t.string :ip_address
          t.timestamps
        end
      end
    
      def self.down
        drop_table :impressions
      end
    end
    

    Add a line to your Article model for the association and add a method to return the impression count:

    class Article < ActiveRecord::Base
      has_many :impressions, :as=>:impressionable
    
      def impression_count
        impressions.size
      end
    
      def unique_impression_count
        # impressions.group(:ip_address).size gives => {'127.0.0.1'=>9, '0.0.0.0'=>1}
        # so getting keys from the hash and calculating the number of keys
        impressions.group(:ip_address).size.keys.length #TESTED
      end
    end
    

    Create a before_filter for articles_controller on the show action:

    before_filter :log_impression, :only=> [:show]
    
    def log_impression
      @article = Article.find(params[:id])
      # this assumes you have a current_user method in your authentication system
      @article.impressions.create(ip_address: request.remote_ip,user_id:current_user.id)
    end
    

    Then you just call the unique_impression_count in your view

    <%=@article.unique_impression_count %>
    

    If you are using this on a bunch of models, you may want to DRY it up. Put the before_filter def in application_controller and use something dynamic like:

    impressionable_class = controller_name.gsub("Controller","").constantize
    impressionable_instance = impressionable_class.find(params[:id])
    impressionable_instance.impressions.create(ip_address:request.remote_ip,user_id:current_user.id)
    

    And also move the code in the Article model to a module that will be included in ActiveRecord::Base. You could put the send include in a config/initializer.. or if you want to get crazy, just turn the whole thing into a rails engine, so you can reuse on other apps.

    module Impressionable
      def is_impressionable
        has_many :impressions, :as=>:impressionable
        include InstanceMethods
      end
      module InstanceMethods
        def impression_count
          impressions.size
        end
    
        def unique_impression_count
          impressions.group(:ip_address).size
        end
      end
    end
    
    ActiveRecord::Base.extend Impressionable
    
    0 讨论(0)
提交回复
热议问题