Gemfile
gem 'impressionist',
git: '[email protected]:charlotte-ruby/impressionist.git',
ref: '46a582ff8cd3496da64f174b30b91f9d97e86643'db/migrate/xxxxxxxxxxxxxxx_add_impressions_count_to_product.rb
class AddImpressionsCountToProduct < ActiveRecord::Migration[6.1]
def change
add_column :products, :visits, :integer, default: 0
end
enddb/migrate/xxxxxxxxxxxxxxx_add_impressions_count_to_service.rb
class AddImpressionsCountToService < ActiveRecord::Migration[6.1]
def change
add_column :services, :visits, :integer, default: 0
end
endapp/models/product.rb
has_many :impressions, as: :impressionable
is_impressionable counter_cache: true, column_name: :visits, unique: :ip_addressapp/models/service.rb
has_many :impressions, as: :impressionable
is_impressionable counter_cache: true, column_name: :visits, unique: :ip_addressapp/models/count_view.rb
class CountView < Impression
# hash по активності перегляду, sample - CountView.hit_by_type(:product) -> {53344=>12, 86499=>10, 6142=>2}
scope :hit_by_type, -> (type) do
klass = type.to_s.camelize.constantize
# klass.where.not(visits: 0).group(:id, :visits).order(visits: :desc).pluck(:id, :visits) # products Array [[53344, 12], [86499, 10], [6142, 1]]
# klass.where.not(visits: 0).joins(:impressions).order(visits: :desc).group(:id, :visits).pluck(:id, :visits) # products Array [[53344, 12], [86499, 10], [6142, 1]]
# klass.where.not(visits: 0).joins(:impressions).order(visits: :desc).group(:visits).count # countview Hash {12=>12, 10=>10, 1=>5}
klass.where.not(visits: 0).joins(:impressions).order(visits: :desc).group(:id).count # products Hash {53344=>12, 86499=>10, 6142=>2, 54632=>1}
end
# relations по найчастіше переглянутим items (by type), sample - CountView.by_visits(:product)
scope :by_visits, -> (type, limit = 20) do
klass = type.to_s.camelize.constantize
klass.where.not(visits: 0).order(visits: :desc).take(limit) # @most_viewed = Product.order('visits DESC').take(20)
end
# relations by type model (необідний тип 'Product' or 'Service'), sample - CountView.by_type(:product)
scope :by_type, -> (type) do
type = type.to_s.camelize
where(impressionable_type: type)
end
# hash по id користувачів, які найчастіше переглядали items, приклад - CountView.most_visitors = CountView.order(:user_id).group(:user_id).count -> {7=>30, 1170=>5}
scope :most_visitors, -> do
order(:user_id).group(:user_id).count
end
# переглянуті користувачем товари (унікальні) - id
scope :products_ids_visited_by_user, -> (user_id) do
where(user_id: user_id)
.select{ |item| item.impressionable_type == 'Product' }
.pluck(:impressionable_id)
.uniq
end
# переглянуті користувачем сервіси (унікальні) - id
scope :services_ids_visited_by_user, -> (user_id) do
where(user_id: user_id)
.select{ |item| item.impressionable_type == 'Service' }
.pluck(:impressionable_id)
.uniq
end
# вибірка по інтервалу, приклад - CountView.by_type(:product).for_date_range(7.days.ago, 1.days.ago)
# приклад chained - CountView.by_type(:product).for_date_range(1.days.ago, Date.today).uniq_count_by_date
scope :for_date_range, -> (start_date, end_date) do
where(created_at: start_date.beginning_of_day..end_date.end_of_day)
end
# групуємо перегляди за кількостю & датах - CountView.by_type(:product).count_by_date
scope :count_by_date, -> do
group('date(created_at)').count
end
# групуємо унікальні перегляди за кількостю & датах - CountView.by_type(:product).uniq_count_by_date (filter by ip_address)
scope :uniq_count_by_date, -> do
select(:ip_address).distinct.count_by_date
end
endapp/controllers/products_controller.rb
def show
impressionist(product) # impressionist(product, nil, { unique: [:session_hash] })app/views/products/show.html.erb
<div class="showbox" data-product-uniq-count='<%= @product.impressionist_count(filter: :ip_address) %>'>