Class: Cursory::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/cursory/base.rb

Direct Known Subclasses

Mongoid

Defined Under Namespace

Classes: InvalidCursorError

Constant Summary collapse

MAX_LIMIT =
100

Instance Method Summary collapse

Constructor Details

#initialize(criteria, params) ⇒ Base

Returns a new instance of Base.



10
11
12
13
14
15
16
# File 'lib/cursory/base.rb', line 10

def initialize criteria, params
  @criteria = criteria
  @sort = params[SORT_KEY]
  @limit = params[LIMIT_KEY]
  @offset = params[OFFSET_KEY]
  @cursor = params[CURSOR_KEY]
end

Instance Method Details

#clamped_limitObject



96
97
98
# File 'lib/cursory/base.rb', line 96

def clamped_limit
  [1, limit.to_i, MAX_LIMIT].sort[1]
end

#clamped_offsetObject



34
35
36
# File 'lib/cursory/base.rb', line 34

def clamped_offset
  [0, offset.to_i].max
end

#clause_for_key(key, direction) ⇒ Object



124
125
126
# File 'lib/cursory/base.rb', line 124

def clause_for_key key, direction
  fail UnimplementedError
end

#constrained_searchObject



38
39
40
# File 'lib/cursory/base.rb', line 38

def constrained_search
  fail UnimplementedError
end

#countObject



64
65
66
# File 'lib/cursory/base.rb', line 64

def count
  @count ||= criteria.count
end

#current_cursorObject



50
51
52
# File 'lib/cursory/base.rb', line 50

def current_cursor
  cursor || render_cursor
end

#cursor_clause(key, keys = []) ⇒ Object



114
115
116
117
118
119
120
121
122
# File 'lib/cursory/base.rb', line 114

def cursor_clause(key, keys=[])
  name, direction = key
  Enumerator.new do |y|
    keys.each do |name, direction|
      y.yield clause_for_key(name, 'eq')
    end
    y.yield clause_for_key(name, direction)
  end
end

#cursor_clause_setObject



104
105
106
107
108
109
110
111
112
# File 'lib/cursory/base.rb', line 104

def cursor_clause_set
  keys = []
  Enumerator.new do |y|
    order_keys.each do |key|
      y.yield cursor_clause(key, keys).reduce(&:merge)
      keys << key
    end
  end
end

#cursor_clausesObject



100
101
102
# File 'lib/cursory/base.rb', line 100

def cursor_clauses
  fail UnimplementedError
end

#cursor_data(overrides = {}) ⇒ Object



150
151
152
# File 'lib/cursory/base.rb', line 150

def cursor_data(overrides={})
  (parsed_cursor || {}).merge(overrides)
end

#cursor_idObject



146
147
148
# File 'lib/cursory/base.rb', line 146

def cursor_id
  cursor_data['id']
end

#cursor_objectObject



128
129
130
# File 'lib/cursory/base.rb', line 128

def cursor_object
  @cursor_object ||= uncached_cursor_object
end

#decompose_order_key(k) ⇒ Object



88
89
90
# File 'lib/cursory/base.rb', line 88

def decompose_order_key(k)
  [ k.gsub(/\A[-+]?/,'').to_sym, k.start_with?('-') ? 'desc' : 'asc' ]
end

#modelObject



76
77
78
# File 'lib/cursory/base.rb', line 76

def model
  fail UnimplementedError
end

#model_sortObject



80
81
82
# File 'lib/cursory/base.rb', line 80

def model_sort
  model.respond_to?(:default_sort_key) && model.default_sort_key
end

#next_cursorObject



58
59
60
61
62
# File 'lib/cursory/base.rb', line 58

def next_cursor
  if record_for_next_cursor
    render_cursor cursor_data(id: record_for_next_cursor.id.to_s)
  end
end

#order_clauseObject



92
93
94
# File 'lib/cursory/base.rb', line 92

def order_clause
  fail UnimplementedError
end

#order_keysObject



84
85
86
# File 'lib/cursory/base.rb', line 84

def order_keys
  sort_keys.split(',').map{ |k| decompose_order_key(k) } + [[:id, 'asc']]
end

#pageObject



18
19
20
21
22
23
24
# File 'lib/cursory/base.rb', line 18

def page
  { total_count: count, items: search_results, self: current_cursor }.tap do |p|
    catch(:no_more_results) do
      p[:next] = next_cursor
    end
  end
end

#parsed_cursorObject



140
141
142
143
144
# File 'lib/cursory/base.rb', line 140

def parsed_cursor
  JSON.parse(::Base64.urlsafe_decode64(cursor || 'e30='))
rescue ArgumentError, JSON::ParserError
  raise InvalidCursorError
end

#record_for_next_cursorObject



54
55
56
# File 'lib/cursory/base.rb', line 54

def record_for_next_cursor
  search_results[clamped_limit-1] or throw(:no_more_results)
end

#render_cursor(data = {}) ⇒ Object



136
137
138
# File 'lib/cursory/base.rb', line 136

def render_cursor(data={})
  ::Base64.urlsafe_encode64(JSON.dump(data))
end

#searchObject



26
27
28
# File 'lib/cursory/base.rb', line 26

def search
  constrained_search.send(*search_type)
end

#search_resultsObject



42
43
44
# File 'lib/cursory/base.rb', line 42

def search_results
  @results ||= uncached_search
end

#search_typeObject



30
31
32
# File 'lib/cursory/base.rb', line 30

def search_type
  fail UnimplementedError
end

#sort_keysObject



72
73
74
# File 'lib/cursory/base.rb', line 72

def sort_keys
  sort || model_sort || ''
end

#uncached_countObject



68
69
70
# File 'lib/cursory/base.rb', line 68

def uncached_count
  fail UnimplementedError
end

#uncached_cursor_objectObject



132
133
134
# File 'lib/cursory/base.rb', line 132

def uncached_cursor_object
  fail UnimplementedError
end

#uncached_searchObject



46
47
48
# File 'lib/cursory/base.rb', line 46

def uncached_search
  fail UnimplementedError
end