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
|
# File 'lib/jsonapionify/api/resource/definitions/pagination.rb', line 22
def self.extended(klass)
klass.class_eval do
include InstanceMethods
inherited_hash_attribute :pagination_strategies
'Object' do |collection|
collection
end
'Enumerable' do |collection, params, links, per, context|
size = Integer(params['first'] || params['last'] || per)
slice =
if (params['before'] && params['first']) || (params['after'] && params['last'])
error :forbidden do
detail 'Illegal combination of parameters'
end
elsif (after = params['after'])
key_values = parse_and_validate_cursor(:after, after, context)
array_select_past_cursor(collection, context.sort_params, key_values).first(size)
elsif (before = params['before'])
key_values = parse_and_validate_cursor(:before, before, context)
array_select_past_cursor(collection, context.sort_params.invert, key_values).last(size)
elsif params['last']
collection.last(size)
else
collection.first(size)
end
context.meta[:total_count] = collection.count
links.first first: size
links.last last: size
links.prev before: build_cursor(context: context, instance: slice.first), last: size unless !slice.first || slice.first == collection.first
links.next after: build_cursor(context: context, instance: slice.last), first: size unless !slice.last || slice.last == collection.last
slice
end
'ActiveRecord::Relation' do |collection, params, links, per, context|
size = Integer(params['first'] || params['last'] || per)
slice =
if (params['before'] && params['first']) || (params['after'] && params['last'])
error :forbidden do
detail 'Illegal combination of parameters'
end
elsif (after = params['after'])
key_values = parse_and_validate_cursor(:after, after, context)
arel_select_past_cursor(collection, context.sort_params, key_values).limit(size)
elsif (before = params['before'])
key_values = parse_and_validate_cursor(:before, before, context)
ids = arel_select_past_cursor(collection, context.sort_params.invert, key_values)
.reverse_order.limit(size).pluck(id_attribute)
collection.where(id_attribute => ids)
elsif params['last']
ids = collection.reverse_order.limit(size).pluck(id_attribute)
collection.where(id_attribute => ids).limit(size)
else
collection.limit(size)
end
context.meta[:total_count] = collection.count
links.first first: size
links.last last: size
links.prev before: build_cursor(context: context, instance: slice.first), last: size unless !slice.first || slice.first == collection.first
links.next after: build_cursor(context: context, instance: slice.last), first: size unless !slice.last || slice.last == collection.last
slice
end
end
end
|