web-dev-qa-db-ja.com

rails

この問題のいくつかの解決策を見つけました。たとえば、この投稿のrailstatです。

Railsのページビュー

独自のIPでフィルターされたヒットカウンターが欲しい記事やレビューがたくさんあります。 Stackoverflowがこの投稿に対して行うのとまったく同じです。しかし、Googleアナリティクスがすでにこれを実行していて、大量のコードを含めたり、一意のIPを追跡したりしている場合、私はrailstatのようなソリューションにはあまり関心がありません。私の現在の考えはGarbまたは他のアナリティクスを使用することですプラグインを使用して、ページが12時間以上経過している場合にページの統計情報をプルしますが、cache_columnも必要です。

Analyticsから特定のページの統計情報を取得でき、それらが12時間ごとに統計情報を更新すると想定していますか?

これが悪い考えになる理由があるのか​​、誰かがより良い解決策を持っているのだろうか?

ありがとう

37
holden

[〜#〜]更新[〜#〜]

この回答のコードは http://github.com/charlotte-Ruby/impressionist の基礎として使用されました


これをアプリにコード化する時間は、APIを使用してAnalyticsからデータを取得するよりも時間がかかりません。このデータはより正確である可能性が高く、外部の依存関係に依存する必要はありません。また、Analyticsデータで12時間待機する代わりに、リアルタイムで統計を取得できます。 request.remote_ipはかなりうまくいきます。以下は、ポリモーフィズムを使用したソリューションです。このコードはテストされていませんが、近いはずです。

新しいモデル/マイグレーションを作成して、ページビュー(インプレッション)を保存します。

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

関連のArticleモデルに行を追加し、インプレッション数を返すメソッドを追加します。

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

Showアクションで、articles_controllerのbefore_filterを作成します。

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

次に、ビューでunique_impression_countを呼び出すだけです

<%[email protected]_impression_count %>

これを一連のモデルで使用している場合は、DRY it up。before_filter defをapplication_controllerに入れて、次のような動的なものを使用します。

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)

また、ArticleモデルのコードをActiveRecord :: Baseに含まれるモジュールに移動します。送信インクルードをconfig/initializerに追加することもできます。または、気が狂ったら、すべてをRailsエンジンに変更して、他のアプリで再利用できるようにします。

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
93
johnmcaliley