простой счетчик посещений для просмотра страниц в рельсах - PullRequest
37 голосов
/ 27 января 2011

Я нашел несколько решений этой проблемы, например, Railstat из этого поста:

Просмотры страниц в Rails

У меня есть куча статей и обзоров, которые я хотел бы, чтобы счетчик посещений отфильтровывался по уникальным IP-адресам. Точно так же, как Stackoverflow делает для этого поста. Но я не очень заинтересован в таком решении, как Railstat, когда Google Analytics уже делает это для меня, включая большое количество кода, отслеживание уникальных IP-адресов и т. Д. Я сейчас думаю об использовании Garb или какой-либо другой аналитики плагин для получения статистики страниц, если они старше, чем, скажем, 12 часов, обновляя таблицу, но мне также нужен cache_column.

Я предполагаю, что вы можете получить статистику из Google Analytics для конкретной страницы, и они обновляют свою статистику каждые 12 часов?

Мне интересно, есть ли какие-либо причины, почему это было бы плохой идеей, или у кого-то есть лучшее решение?

Спасибо

1 Ответ

94 голосов
/ 27 января 2011

ОБНОВЛЕНИЕ

Код в этом ответе использовался в качестве основы для http://github.com/charlotte-ruby/impressionist Попробуйте это


Возможно, это займет у васменьше времени, чтобы закодировать это в ваше приложение, тогда было бы извлечь данные из Google Analytics, используя их API.Эти данные, скорее всего, будут более точными, и вам не придется полагаться на внешнюю зависимость. Кроме того, вы будете получать статистику в режиме реального времени, а не ждать 12 часов с данными Analytics.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

Добавьте строку в свою статьюмодели для ассоциации и добавьте метод для возврата количества показов:

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

Создайте before_filter для article_controller в действии show:

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 вview

<%=@article.unique_impression_count %>

Если вы используете это на нескольких моделях, вы можете захотеть высушить его.Поместите def before_filter в 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.Вы можете поместить send include в 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
...