~cytrogen/masto-fe

ref: 86ba8d3e14955841fed45b49114e06b7a3473ba4 masto-fe/app/models/trends/query.rb -rw-r--r-- 1.9 KiB
86ba8d3e — Claire Merge pull request #2368 from ClearlyClaire/glitch-soc/merge-upstream 2 years ago
                                                                                
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
110
111
112
113
114
115
116
117
118
119
120
121
# 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
    if ids_for_key.empty?
      klass.none
    else
      scope = klass.joins(sanitized_join_sql).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_for_key
    @ids_for_key ||= redis.zrevrange(key, 0, -1).map(&:to_i)
  end

  def sanitized_join_sql
    ActiveRecord::Base.sanitize_sql_array(join_sql_array)
  end

  def join_sql_array
    [join_sql_query, ids_for_key]
  end

  def join_sql_query
    <<~SQL.squish
      JOIN unnest(array[?]) WITH ordinality AS x (id, ordering) ON #{klass.table_name}.id = x.id
    SQL
  end

  def perform_queries
    apply_scopes(to_arel).to_a
  end

  def apply_scopes(scope)
    scope
  end
end