-
Notifications
You must be signed in to change notification settings - Fork 49
/
convenience.rb
117 lines (102 loc) · 3.17 KB
/
convenience.rb
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
module Picky
# Use this class to extend the hash that the client returns.
#
module Convenience
# Are there any allocations?
#
def empty?
allocations.empty?
end
# Returns the topmost n results.
# (Note that not all ids are returned with the results. By default only maximally 20.)
#
# === Parameters
# * limit: The amount of ids to return. Default is 20.
#
def ids limit = 20
ids = []
allocations.each { |allocation| allocation[4].each { |id| break if ids.size > limit; ids << id } }
ids
end
# Removes all ids of each allocation.
#
def clear_ids
allocations.each { |allocation| allocation[4].clear }
end
# Returns the allocations.
#
def allocations
@allocations || @allocations = self[:allocations]
end
# Returns the number of allocations.
#
def allocations_size
@allocations_size || @allocations_size = allocations.size
end
# Returns the total of results.
#
def total
@total || @total = self[:total]
end
# Populates the ids with (rendered) model instances.
#
# Give it an AR class and options for the find and it
# will yield each found result for you to render.
#
# If you don't pass it a block, it will just use the AR results.
#
# === Parameters
# * model_class: The model to use for the results. Will call #find on the given class.
# * amount: Amount of results to populate. Default 20.
#
# === Options
# * options are directly passed through to the ModelClass.find(ids, options) method. Default is {}.
#
def populate_with model_class, amount = 20, options = {}, &block
the_ids = ids amount
objects = model_class.find the_ids, options
# Put together a mapping.
#
mapped_entries = objects.inject({}) do |mapped, entry|
mapped[entry.id] = entry if entry
mapped
end
# Preserves the order
#
objects = the_ids.map { |id| mapped_entries[id] }
objects.collect! &block if block_given?
amend_ids_with objects
clear_ids
objects
end
# Returns either
# * the rendered entries, if you have used #populate_with _with_ a block
# OR
# * the model instances, if you have used #populate_with _without_ a block
#
# Or, if you haven't called #populate_with yet, you will get an empty array.
#
def entries limit = 20
if block_given?
i = 0
allocations.each { |allocation| allocation[5].collect! { |ar_or_rendered| break if i >= limit; i = i + 1; yield ar_or_rendered } }
else
entries = []
allocations.each { |allocation| allocation[5].each { |ar_or_rendered| break if entries.size >= limit; entries << ar_or_rendered } }
entries
end
end
# The ids need to come in the order which the ids were returned by the ids method.
#
def amend_ids_with entries # :nodoc:
i = 0
self.allocations.each do |allocation|
allocation[5] = allocation[4].map do |_|
e = entries[i]
i += 1
e
end
end
end
end
end