about summary refs log tree commit diff
path: root/app/models/trends/query.rb
blob: cd5571bc62cd4a3612c7563f3fccbac1ef18a514 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# frozen_string_literal: true

class Trends::Query
  include Redisable
  include Enumerable

  attr_reader :prefix, :klass, :loaded

  alias loaded? loaded

  def initialize(prefix, klass)
    @prefix  = prefix
    @klass   = klass
    @records = []
    @loaded  = false
    @allowed = false
    @limit   = nil
    @offset  = nil
  end

  def allowed!
    @allowed = true
    self
  end

  def allowed
    clone.allowed!
  end

  def in_locale!(value)
    @locale = value
    self
  end

  def in_locale(value)
    clone.in_locale!(value)
  end

  def offset!(value)
    @offset = value.to_i
    self
  end

  def offset(value)
    clone.offset!(value)
  end

  def limit!(value)
    @limit = value.to_i
    self
  end

  def limit(value)
    clone.limit!(value)
  end

  def records
    load
    @records
  end

  delegate :each, :empty?, :first, :last, :size, to: :records

  def to_ary
    records.dup
  end

  alias to_a to_ary

  def to_arel
    tmp_ids = ids

    if tmp_ids.empty?
      klass.none
    else
      scope = klass.joins("join unnest(array[#{tmp_ids.join(',')}]) with ordinality as x (id, ordering) on #{klass.table_name}.id = x.id").reorder('x.ordering')
      scope = scope.offset(@offset) if @offset.present?
      scope = scope.limit(@limit) if @limit.present?
      scope
    end
  end

  private

  def key
    [@prefix, @allowed ? 'allowed' : 'all', @locale].compact.join(':')
  end

  def load
    unless loaded?
      @records = perform_queries
      @loaded  = true
    end

    self
  end

  def ids
    redis.zrevrange(key, 0, -1).map(&:to_i)
  end

  def perform_queries
    apply_scopes(to_arel).to_a
  end

  def apply_scopes(scope)
    scope
  end
end