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.



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

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



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

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

#clamped_offsetObject



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

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

#clause_for_key(key, direction) ⇒ Object



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

def clause_for_key key, direction
  fail UnimplementedError
end

#constrained_searchObject



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

def constrained_search
  fail UnimplementedError
end

#countObject



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

def count
  @count ||= criteria.count
end

#current_cursorObject



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

def current_cursor
  cursor || render_cursor
end

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



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

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



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

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



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

def cursor_clauses
  fail UnimplementedError
end

#cursor_data(overrides = {}) ⇒ Object



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

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

#cursor_idObject



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

def cursor_id
  cursor_data['id']
end

#cursor_objectObject



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

def cursor_object
  @cursor_object ||= uncached_cursor_object
end

#decompose_order_key(k) ⇒ Object



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

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

#modelObject



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

def model
  fail UnimplementedError
end

#model_sortObject



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

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

#next_cursorObject



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

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

#order_clauseObject



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

def order_clause
  fail UnimplementedError
end

#order_keysObject



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

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

#pageObject



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

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



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

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

#record_for_next_cursorObject



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

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

#render_cursor(data = {}) ⇒ Object



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

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

#searchObject



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

def search
  constrained_search.send(*search_type)
end

#search_resultsObject



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

def search_results
  @results ||= uncached_search
end

#search_typeObject



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

def search_type
  fail UnimplementedError
end

#sort_keysObject



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

def sort_keys
  sort || model_sort || ''
end

#uncached_countObject



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

def uncached_count
  fail UnimplementedError
end

#uncached_cursor_objectObject



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

def uncached_cursor_object
  fail UnimplementedError
end

#uncached_searchObject



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

def uncached_search
  fail UnimplementedError
end