Skip to content

Instantly share code, notes, and snippets.

@secretpray
Last active June 30, 2022 05:28
Show Gist options
  • Save secretpray/2dcac616fbbcf7cbed41b737a7de842a to your computer and use it in GitHub Desktop.
Save secretpray/2dcac616fbbcf7cbed41b737a7de842a to your computer and use it in GitHub Desktop.
impressionist gem Rails 6 with Turbo and webpacker

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
end

db/migrate/xxxxxxxxxxxxxxx_add_impressions_count_to_service.rb

class AddImpressionsCountToService < ActiveRecord::Migration[6.1]
  def change
    add_column :services, :visits, :integer, default: 0
  end
end

app/models/product.rb

 has_many :impressions, as: :impressionable
 is_impressionable counter_cache: true, column_name: :visits, unique: :ip_address

app/models/service.rb

has_many :impressions, as: :impressionable
is_impressionable counter_cache: true, column_name: :visits, unique: :ip_address

app/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
end

app/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) %>'>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment