ujh/fountainpencompanion

View on GitHub
app/models/leader_board.rb

Summary

Maintainability
A
2 hrs
Test Coverage
class LeaderBoard
  TYPES = %w[
    inks
    bottles
    samples
    inks_by_popularity
    currently_inked
    usage_records
    pens_by_popularity
    ink_review_submissions
  ]

  WORKERS = TYPES.map { |t| "refresh_leader_board/#{t}".camelize.constantize }

  def self.refresh!(type)
    self.send(type, force: true)
  end

  def self.users_by_description_edits(force: false)
    LeaderBoardRow::DescriptionEdits.to_leader_board
  end

  def self.top_users_by_description_edits
    LeaderBoardRow::DescriptionEdits.limit(10).to_leader_board
  end

  def self.pens_by_popularity(force: false)
    Rails
      .cache
      .fetch("LeaderBoard#pens_by_popularity", force: force) do
        CollectedPen
          .group("lower(concat(brand, model))")
          .where(archived_on: nil)
          .select(
            "initcap(min(brand)) as brand, initcap(min(model)) as model, count(id) as count"
          )
          .having("count(distinct user_id) > 1")
          .order("count desc")
      end
  end

  def self.top_pens_by_popularity
    pens_by_popularity.take(10)
  end

  def self.ink_review_submissions(force: false)
    Rails
      .cache
      .fetch("LeaderBoard#ink_review_submissions", force: force) do
        relation =
          User
            .where("users.id <> 1")
            .joins(:ink_review_submissions)
            .select("users.*, count(*) as counter")
            .group("users.id")
            .order("counter DESC")
        extract(relation)
      end
  end

  def self.top_ink_review_submissions
    ink_review_submissions.take(10)
  end

  def self.usage_records(force: false)
    Rails
      .cache
      .fetch("LeaderBoard#usage_records", force: force) do
        relation =
          User
            .joins(currently_inkeds: :usage_records)
            .select("users.*, count(*) as counter")
            .group("users.id")
            .order("counter DESC")
        extract(relation)
      end
  end

  def self.top_usage_records
    usage_records.take(10)
  end

  def self.currently_inked(force: false)
    Rails
      .cache
      .fetch("LeaderBoard#currently_inked", force: force) do
        relation =
          User
            .joins(:currently_inkeds)
            .select("users.*, count(*) as counter")
            .group("users.id")
            .order("counter DESC")
        extract(relation)
      end
  end

  def self.top_currently_inked
    currently_inked.take(10)
  end

  def self.inks_by_popularity(force: false)
    Rails
      .cache
      .fetch("LeaderBoard#inks_by_popularity", force: force) do
        MacroCluster
          .joins(micro_clusters: :collected_inks)
          .includes(:brand_cluster)
          .where(collected_inks: { private: false })
          .group("macro_clusters.id")
          .select("macro_clusters.*, count(macro_clusters.id) as ci_count")
          .order("ci_count desc")
      end
  end

  def self.top_inks_by_popularity
    inks_by_popularity.take(10)
  end

  def self.inks(force: false)
    Rails.cache.fetch("LeaderBoard#inks", force: force) { extract(build) }
  end

  def self.top_inks
    inks.take(10)
  end

  def self.bottles(force: false)
    Rails
      .cache
      .fetch("LeaderBoard#bottles", force: force) do
        extract(build.where(collected_inks: { kind: "bottle" }))
      end
  end

  def self.top_bottles
    bottles.take(10)
  end

  def self.samples(force: false)
    Rails
      .cache
      .fetch("LeaderBoard#samples", force: force) do
        extract(build.where(collected_inks: { kind: "sample" }))
      end
  end

  def self.top_samples
    samples.take(10)
  end

  def self.brands(force: false)
    LeaderBoardRow::Brands.to_leader_board
  end

  def self.top_brands
    LeaderBoardRow::Brands.limit(10).to_leader_board
  end

  def self.build(select = "count(*) as counter")
    select_clause = "users.*, #{select}"
    base_relation.select(select_clause)
  end

  def self.base_relation
    User
      .joins(:collected_inks)
      .where(collected_inks: { archived_on: nil, private: false })
      .group("users.id")
      .order("counter DESC")
  end

  def self.extract(relation)
    relation.map do |i|
      {
        id: i.id,
        public_name: i.public_name,
        counter: i.counter,
        patron: i.patron
      }
    end
  end
end