ОБНОВЛЕНИЕ
Код в этом ответе использовался в качестве основы для 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