query.rb 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. # frozen_string_literal: true
  2. class Trends::Query
  3. include Redisable
  4. include Enumerable
  5. attr_reader :prefix, :klass, :loaded
  6. alias loaded? loaded
  7. def initialize(prefix, klass)
  8. @prefix = prefix
  9. @klass = klass
  10. @records = []
  11. @loaded = false
  12. @allowed = false
  13. @limit = nil
  14. @offset = nil
  15. end
  16. def allowed!
  17. @allowed = true
  18. self
  19. end
  20. def allowed
  21. clone.allowed!
  22. end
  23. def in_locale!(value)
  24. @locale = value
  25. self
  26. end
  27. def in_locale(value)
  28. clone.in_locale!(value)
  29. end
  30. def offset!(value)
  31. @offset = value.to_i
  32. self
  33. end
  34. def offset(value)
  35. clone.offset!(value)
  36. end
  37. def limit!(value)
  38. @limit = value.to_i
  39. self
  40. end
  41. def limit(value)
  42. clone.limit!(value)
  43. end
  44. def records
  45. load
  46. @records
  47. end
  48. delegate :each, :empty?, :first, :last, :size, to: :records
  49. def to_ary
  50. records.dup
  51. end
  52. alias to_a to_ary
  53. def to_arel
  54. tmp_ids = ids
  55. if tmp_ids.empty?
  56. klass.none
  57. else
  58. 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')
  59. scope = scope.offset(@offset) if @offset.present?
  60. scope = scope.limit(@limit) if @limit.present?
  61. scope
  62. end
  63. end
  64. private
  65. def key
  66. [@prefix, @allowed ? 'allowed' : 'all', @locale].compact.join(':')
  67. end
  68. def load
  69. unless loaded?
  70. @records = perform_queries
  71. @loaded = true
  72. end
  73. self
  74. end
  75. def ids
  76. redis.zrevrange(key, 0, -1).map(&:to_i)
  77. end
  78. def perform_queries
  79. apply_scopes(to_arel).to_a
  80. end
  81. def apply_scopes(scope)
  82. scope
  83. end
  84. end