ranked-model 0.4.4 → 0.4.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,351 +1,356 @@
1
- module RankedModel
2
-
3
- class InvalidScope < StandardError; end
4
- class InvalidField < StandardError; end
5
-
6
- class Ranker
7
- attr_accessor :name, :column, :scope, :with_same, :class_name, :unless
8
-
9
- def initialize name, options={}
10
- self.name = name.to_sym
11
- self.column = options[:column] || name
12
- self.class_name = options[:class_name]
13
-
14
- [ :scope, :with_same, :unless ].each do |key|
15
- self.send "#{key}=", options[key]
16
- end
17
- end
18
-
19
- def with instance
20
- Mapper.new self, instance
21
- end
22
-
23
- class Mapper
24
- attr_accessor :ranker, :instance
25
-
26
- def initialize ranker, instance
27
- self.ranker = ranker
28
- self.instance = instance
29
-
30
- validate_ranker_for_instance!
31
- end
32
-
33
- def validate_ranker_for_instance!
34
- if ranker.scope && !instance_class.respond_to?(ranker.scope)
35
- raise RankedModel::InvalidScope, %Q{No scope called "#{ranker.scope}" found in model}
36
- end
37
-
38
- if ranker.with_same
39
- if (case ranker.with_same
40
- when Symbol
41
- !instance.respond_to?(ranker.with_same)
42
- when Array
43
- array_element = ranker.with_same.detect {|attr| !instance.respond_to?(attr) }
44
- else
45
- false
46
- end)
47
- raise RankedModel::InvalidField, %Q{No field called "#{array_element || ranker.with_same}" found in model}
48
- end
49
- end
50
- end
51
-
52
- def handle_ranking
53
- case ranker.unless
54
- when Proc
55
- return if ranker.unless.call(instance)
56
- when Symbol
57
- return if instance.send(ranker.unless)
58
- end
59
-
60
- update_index_from_position
61
- assure_unique_position
62
- end
63
-
64
- def update_rank! value
65
- # Bypass callbacks
66
- #
67
- instance_class.
68
- where(instance_class.primary_key => instance.id).
69
- update_all(ranker.column => value)
70
- end
71
-
72
- def position
73
- instance.send "#{ranker.name}_position"
74
- end
75
-
76
- def relative_rank
77
- finder.where("#{ranker.column} < #{rank}").count(:all)
78
- end
79
-
80
- def rank
81
- instance.send "#{ranker.column}"
82
- end
83
-
84
- def current_at_position _pos
85
- if (ordered_instance = finder.offset(_pos).first)
86
- RankedModel::Ranker::Mapper.new ranker, ordered_instance
87
- end
88
- end
89
-
90
- def has_rank?
91
- !rank.nil?
92
- end
93
-
94
- private
95
-
96
- def reset_cache
97
- @finder, @current_order, @current_first, @current_last = nil
98
- end
99
-
100
- def instance_class
101
- ranker.class_name.nil? ? instance.class : ranker.class_name.constantize
102
- end
103
-
104
- def position_at value
105
- instance.send "#{ranker.name}_position=", value
106
- update_index_from_position
107
- end
108
-
109
- def rank_at value
110
- instance.send "#{ranker.column}=", value
111
- end
112
-
113
- def rank_changed?
114
- instance.send "#{ranker.column}_changed?"
115
- end
116
-
117
- def new_record?
118
- instance.new_record?
119
- end
120
-
121
- def update_index_from_position
122
- case position
123
- when :first, 'first'
124
- if current_first && current_first.rank
125
- rank_at_average current_first.rank, RankedModel::MIN_RANK_VALUE
126
- else
127
- position_at :middle
128
- end
129
- when :last, 'last'
130
- if current_last && current_last.rank
131
- rank_at_average current_last.rank, RankedModel::MAX_RANK_VALUE
132
- else
133
- position_at :middle
134
- end
135
- when :middle, 'middle'
136
- rank_at_average RankedModel::MIN_RANK_VALUE, RankedModel::MAX_RANK_VALUE
137
- when :down, 'down'
138
- neighbors = find_next_two(rank)
139
- if neighbors[:lower]
140
- min = neighbors[:lower].rank
141
- max = neighbors[:upper] ? neighbors[:upper].rank : RankedModel::MAX_RANK_VALUE
142
- rank_at_average min, max
143
- end
144
- when :up, 'up'
145
- neighbors = find_previous_two(rank)
146
- if neighbors[:upper]
147
- max = neighbors[:upper].rank
148
- min = neighbors[:lower] ? neighbors[:lower].rank : RankedModel::MIN_RANK_VALUE
149
- rank_at_average min, max
150
- end
151
- when String
152
- position_at position.to_i
153
- when 0
154
- position_at :first
155
- when Integer
156
- neighbors = neighbors_at_position(position)
157
- min = ((neighbors[:lower] && neighbors[:lower].has_rank?) ? neighbors[:lower].rank : RankedModel::MIN_RANK_VALUE)
158
- max = ((neighbors[:upper] && neighbors[:upper].has_rank?) ? neighbors[:upper].rank : RankedModel::MAX_RANK_VALUE)
159
- rank_at_average min, max
160
- when NilClass
161
- if !rank
162
- position_at :last
163
- end
164
- end
165
- end
166
-
167
- def rank_at_average(min, max)
168
- if (max - min).between?(-1, 1) # No room at the inn...
169
- rebalance_ranks
170
- position_at position
171
- else
172
- rank_at( ( ( max - min ).to_f / 2 ).ceil + min )
173
- end
174
- end
175
-
176
- def assure_unique_position
177
- if ( new_record? || rank_changed? )
178
- if (rank > RankedModel::MAX_RANK_VALUE) || current_at_rank(rank)
179
- rearrange_ranks
180
- end
181
- end
182
- end
183
-
184
- def rearrange_ranks
185
- _scope = finder
186
- escaped_column = ActiveRecord::Base.connection.quote_column_name ranker.column
187
- # If there is room at the bottom of the list and we're added to the very top of the list...
188
- if current_first.rank && current_first.rank > RankedModel::MIN_RANK_VALUE && rank == RankedModel::MAX_RANK_VALUE
189
- # ...then move everyone else down 1 to make room for us at the end
190
- _scope.
191
- where( instance_class.arel_table[ranker.column].lteq(rank) ).
192
- update_all( "#{escaped_column} = #{escaped_column} - 1" )
193
- # If there is room at the top of the list and we're added below the last value in the list...
194
- elsif current_last.rank && current_last.rank < (RankedModel::MAX_RANK_VALUE - 1) && rank < current_last.rank
195
- # ...then move everyone else at or above our desired rank up 1 to make room for us
196
- _scope.
197
- where( instance_class.arel_table[ranker.column].gteq(rank) ).
198
- update_all( "#{escaped_column} = #{escaped_column} + 1" )
199
- # If there is room at the bottom of the list and we're added above the lowest value in the list...
200
- elsif current_first.rank && current_first.rank > RankedModel::MIN_RANK_VALUE && rank > current_first.rank
201
- # ...then move everyone else below us down 1 and change our rank down 1 to avoid the collission
202
- _scope.
203
- where( instance_class.arel_table[ranker.column].lt(rank) ).
204
- update_all( "#{escaped_column} = #{escaped_column} - 1" )
205
- rank_at( rank - 1 )
206
- else
207
- rebalance_ranks
208
- end
209
- end
210
-
211
- def rebalance_ranks
212
- if rank && instance.persisted?
213
- origin = current_order.index { |item| item.instance.id == instance.id }
214
- destination = current_order.index { |item| rank <= item.rank }
215
- destination -= 1 if origin < destination
216
-
217
- current_order.insert destination, current_order.delete_at(origin)
218
- end
219
-
220
- gaps = current_order.size + 1
221
- range = (RankedModel::MAX_RANK_VALUE - RankedModel::MIN_RANK_VALUE).to_f
222
- gap_size = (range / gaps).ceil
223
-
224
- current_order.each.with_index(1) do |item, position|
225
- new_rank = (gap_size * position) + RankedModel::MIN_RANK_VALUE
226
-
227
- if item.instance.id == instance.id
228
- rank_at new_rank
229
- else
230
- item.update_rank! new_rank
231
- end
232
- end
233
-
234
- reset_cache
235
- end
236
-
237
- def finder(order = :asc)
238
- @finder ||= {}
239
- @finder[order] ||= begin
240
- _finder = instance_class
241
- columns = [instance_class.primary_key.to_sym, ranker.column]
242
-
243
- if ranker.scope
244
- _finder = _finder.send ranker.scope
245
- end
246
-
247
- case ranker.with_same
248
- when Symbol
249
- columns << ranker.with_same
250
- _finder = _finder.where \
251
- ranker.with_same => instance.attributes[ranker.with_same.to_s]
252
- when Array
253
- ranker.with_same.each do |column|
254
- columns << column
255
- _finder = _finder.where column => instance.attributes[column.to_s]
256
- end
257
- end
258
-
259
- unless new_record?
260
- _finder = _finder.where.not instance_class.primary_key.to_sym => instance.id
261
- end
262
-
263
- _finder.reorder(ranker.column.to_sym => order).select(columns)
264
- end
265
- end
266
-
267
- def current_order
268
- @current_order ||= begin
269
- finder.unscope(where: instance_class.primary_key.to_sym).collect { |ordered_instance|
270
- RankedModel::Ranker::Mapper.new ranker, ordered_instance
271
- }
272
- end
273
- end
274
-
275
- def current_first
276
- @current_first ||= begin
277
- if (ordered_instance = finder.first)
278
- RankedModel::Ranker::Mapper.new ranker, ordered_instance
279
- end
280
- end
281
- end
282
-
283
- def current_last
284
- @current_last ||= begin
285
- if (ordered_instance = finder.
286
- reverse.
287
- first)
288
- RankedModel::Ranker::Mapper.new ranker, ordered_instance
289
- end
290
- end
291
- end
292
-
293
- def current_at_rank _rank
294
- if (ordered_instance = finder.
295
- except( :order ).
296
- where( ranker.column => _rank ).
297
- first)
298
- RankedModel::Ranker::Mapper.new ranker, ordered_instance
299
- end
300
- end
301
-
302
- def neighbors_at_position _pos
303
- if _pos > 0
304
- if (ordered_instances = finder.offset(_pos-1).limit(2).to_a)
305
- if ordered_instances[1]
306
- { :lower => RankedModel::Ranker::Mapper.new( ranker, ordered_instances[0] ),
307
- :upper => RankedModel::Ranker::Mapper.new( ranker, ordered_instances[1] ) }
308
- elsif ordered_instances[0]
309
- { :lower => RankedModel::Ranker::Mapper.new( ranker, ordered_instances[0] ) }
310
- else
311
- { :lower => current_last }
312
- end
313
- end
314
- else
315
- if (ordered_instance = finder.first)
316
- { :upper => RankedModel::Ranker::Mapper.new( ranker, ordered_instance ) }
317
- else
318
- {}
319
- end
320
- end
321
- end
322
-
323
- def find_next_two _rank
324
- ordered_instances = finder.where(instance_class.arel_table[ranker.column].gt _rank).limit(2)
325
- if ordered_instances[1]
326
- { :lower => RankedModel::Ranker::Mapper.new( ranker, ordered_instances[0] ),
327
- :upper => RankedModel::Ranker::Mapper.new( ranker, ordered_instances[1] ) }
328
- elsif ordered_instances[0]
329
- { :lower => RankedModel::Ranker::Mapper.new( ranker, ordered_instances[0] ) }
330
- else
331
- {}
332
- end
333
- end
334
-
335
- def find_previous_two _rank
336
- ordered_instances = finder(:desc).where(instance_class.arel_table[ranker.column].lt _rank).limit(2)
337
- if ordered_instances[1]
338
- { :upper => RankedModel::Ranker::Mapper.new( ranker, ordered_instances[0] ),
339
- :lower => RankedModel::Ranker::Mapper.new( ranker, ordered_instances[1] ) }
340
- elsif ordered_instances[0]
341
- { :upper => RankedModel::Ranker::Mapper.new( ranker, ordered_instances[0] ) }
342
- else
343
- {}
344
- end
345
- end
346
-
347
- end
348
-
349
- end
350
-
351
- end
1
+ module RankedModel
2
+
3
+ class InvalidScope < StandardError; end
4
+ class InvalidField < StandardError; end
5
+
6
+ class Ranker
7
+ attr_accessor :name, :column, :scope, :with_same, :class_name, :unless
8
+
9
+ def initialize name, options={}
10
+ self.name = name.to_sym
11
+ self.column = options[:column] || name
12
+ self.class_name = options[:class_name]
13
+
14
+ [ :scope, :with_same, :unless ].each do |key|
15
+ self.send "#{key}=", options[key]
16
+ end
17
+ end
18
+
19
+ def with instance
20
+ Mapper.new self, instance
21
+ end
22
+
23
+ class Mapper
24
+ attr_accessor :ranker, :instance
25
+
26
+ def initialize ranker, instance
27
+ self.ranker = ranker
28
+ self.instance = instance
29
+
30
+ validate_ranker_for_instance!
31
+ end
32
+
33
+ def validate_ranker_for_instance!
34
+ if ranker.scope && !instance_class.respond_to?(ranker.scope)
35
+ raise RankedModel::InvalidScope, %Q{No scope called "#{ranker.scope}" found in model}
36
+ end
37
+
38
+ if ranker.with_same
39
+ if (case ranker.with_same
40
+ when Symbol
41
+ !instance.respond_to?(ranker.with_same)
42
+ when Array
43
+ array_element = ranker.with_same.detect {|attr| !instance.respond_to?(attr) }
44
+ else
45
+ false
46
+ end)
47
+ raise RankedModel::InvalidField, %Q{No field called "#{array_element || ranker.with_same}" found in model}
48
+ end
49
+ end
50
+ end
51
+
52
+ def handle_ranking
53
+ case ranker.unless
54
+ when Proc
55
+ return if ranker.unless.call(instance)
56
+ when Symbol
57
+ return if instance.send(ranker.unless)
58
+ end
59
+
60
+ update_index_from_position
61
+ assure_unique_position
62
+ end
63
+
64
+ def update_rank! value
65
+ # Bypass callbacks
66
+ #
67
+ instance_class.
68
+ where(instance_class.primary_key => instance.id).
69
+ update_all(ranker.column => value)
70
+ end
71
+
72
+ def reset_ranks!
73
+ finder.update_all(ranker.column => nil)
74
+ end
75
+
76
+ def position
77
+ instance.send "#{ranker.name}_position"
78
+ end
79
+
80
+ def relative_rank
81
+ escaped_column = instance_class.connection.quote_column_name ranker.column
82
+
83
+ finder.where("#{escaped_column} < #{rank}").count(:all)
84
+ end
85
+
86
+ def rank
87
+ instance.send "#{ranker.column}"
88
+ end
89
+
90
+ def current_at_position _pos
91
+ if (ordered_instance = finder.offset(_pos).first)
92
+ RankedModel::Ranker::Mapper.new ranker, ordered_instance
93
+ end
94
+ end
95
+
96
+ def has_rank?
97
+ !rank.nil?
98
+ end
99
+
100
+ private
101
+
102
+ def reset_cache
103
+ @finder, @current_order, @current_first, @current_last = nil
104
+ end
105
+
106
+ def instance_class
107
+ ranker.class_name.nil? ? instance.class : ranker.class_name.constantize
108
+ end
109
+
110
+ def position_at value
111
+ instance.send "#{ranker.name}_position=", value
112
+ update_index_from_position
113
+ end
114
+
115
+ def rank_at value
116
+ instance.send "#{ranker.column}=", value
117
+ end
118
+
119
+ def rank_changed?
120
+ instance.send "#{ranker.column}_changed?"
121
+ end
122
+
123
+ def new_record?
124
+ instance.new_record?
125
+ end
126
+
127
+ def update_index_from_position
128
+ case position
129
+ when :first, 'first'
130
+ if current_first && current_first.rank
131
+ rank_at_average current_first.rank, RankedModel::MIN_RANK_VALUE
132
+ else
133
+ position_at :middle
134
+ end
135
+ when :last, 'last'
136
+ if current_last && current_last.rank
137
+ rank_at_average current_last.rank, RankedModel::MAX_RANK_VALUE
138
+ else
139
+ position_at :middle
140
+ end
141
+ when :middle, 'middle'
142
+ rank_at_average RankedModel::MIN_RANK_VALUE, RankedModel::MAX_RANK_VALUE
143
+ when :down, 'down'
144
+ neighbors = find_next_two(rank)
145
+ if neighbors[:lower]
146
+ min = neighbors[:lower].rank
147
+ max = neighbors[:upper] ? neighbors[:upper].rank : RankedModel::MAX_RANK_VALUE
148
+ rank_at_average min, max
149
+ end
150
+ when :up, 'up'
151
+ neighbors = find_previous_two(rank)
152
+ if neighbors[:upper]
153
+ max = neighbors[:upper].rank
154
+ min = neighbors[:lower] ? neighbors[:lower].rank : RankedModel::MIN_RANK_VALUE
155
+ rank_at_average min, max
156
+ end
157
+ when String
158
+ position_at position.to_i
159
+ when 0
160
+ position_at :first
161
+ when Integer
162
+ neighbors = neighbors_at_position(position)
163
+ min = ((neighbors[:lower] && neighbors[:lower].has_rank?) ? neighbors[:lower].rank : RankedModel::MIN_RANK_VALUE)
164
+ max = ((neighbors[:upper] && neighbors[:upper].has_rank?) ? neighbors[:upper].rank : RankedModel::MAX_RANK_VALUE)
165
+ rank_at_average min, max
166
+ when NilClass
167
+ if !rank
168
+ position_at :last
169
+ end
170
+ end
171
+ end
172
+
173
+ def rank_at_average(min, max)
174
+ if (max - min).between?(-1, 1) # No room at the inn...
175
+ rebalance_ranks
176
+ position_at position
177
+ else
178
+ rank_at( ( ( max - min ).to_f / 2 ).ceil + min )
179
+ end
180
+ end
181
+
182
+ def assure_unique_position
183
+ if ( new_record? || rank_changed? )
184
+ if (rank > RankedModel::MAX_RANK_VALUE) || rank_taken?
185
+ rearrange_ranks
186
+ end
187
+ end
188
+ end
189
+
190
+ def rearrange_ranks
191
+ _scope = finder
192
+ escaped_column = instance_class.connection.quote_column_name ranker.column
193
+ # If there is room at the bottom of the list and we're added to the very top of the list...
194
+ if current_first.rank && current_first.rank > RankedModel::MIN_RANK_VALUE && rank == RankedModel::MAX_RANK_VALUE
195
+ # ...then move everyone else down 1 to make room for us at the end
196
+ _scope.
197
+ where( instance_class.arel_table[ranker.column].lteq(rank) ).
198
+ update_all( "#{escaped_column} = #{escaped_column} - 1" )
199
+ # If there is room at the top of the list and we're added below the last value in the list...
200
+ elsif current_last.rank && current_last.rank < (RankedModel::MAX_RANK_VALUE - 1) && rank < current_last.rank
201
+ # ...then move everyone else at or above our desired rank up 1 to make room for us
202
+ _scope.
203
+ where( instance_class.arel_table[ranker.column].gteq(rank) ).
204
+ update_all( "#{escaped_column} = #{escaped_column} + 1" )
205
+ # If there is room at the bottom of the list and we're added above the lowest value in the list...
206
+ elsif current_first.rank && current_first.rank > RankedModel::MIN_RANK_VALUE && rank > current_first.rank
207
+ # ...then move everyone else below us down 1 and change our rank down 1 to avoid the collission
208
+ _scope.
209
+ where( instance_class.arel_table[ranker.column].lt(rank) ).
210
+ update_all( "#{escaped_column} = #{escaped_column} - 1" )
211
+ rank_at( rank - 1 )
212
+ else
213
+ rebalance_ranks
214
+ end
215
+ end
216
+
217
+ def rebalance_ranks
218
+ ActiveRecord::Base.transaction do
219
+ if rank && instance.persisted?
220
+ origin = current_order.index { |item| item.instance.id == instance.id }
221
+ if origin
222
+ destination = current_order.index { |item| rank <= item.rank }
223
+ destination -= 1 if origin < destination
224
+
225
+ current_order.insert destination, current_order.delete_at(origin)
226
+ end
227
+ end
228
+
229
+ gaps = current_order.size + 1
230
+ range = (RankedModel::MAX_RANK_VALUE - RankedModel::MIN_RANK_VALUE).to_f
231
+ gap_size = (range / gaps).ceil
232
+
233
+ reset_ranks!
234
+
235
+ current_order.each.with_index(1) do |item, position|
236
+ new_rank = (gap_size * position) + RankedModel::MIN_RANK_VALUE
237
+
238
+ if item.instance.id == instance.id
239
+ rank_at new_rank
240
+ else
241
+ item.update_rank! new_rank
242
+ end
243
+ end
244
+
245
+ reset_cache
246
+ end
247
+ end
248
+
249
+ def finder(order = :asc)
250
+ @finder ||= {}
251
+ @finder[order] ||= begin
252
+ _finder = instance_class
253
+ columns = [instance_class.primary_key.to_sym, ranker.column]
254
+
255
+ if ranker.scope
256
+ _finder = _finder.send ranker.scope
257
+ end
258
+
259
+ case ranker.with_same
260
+ when Symbol
261
+ columns << ranker.with_same
262
+ _finder = _finder.where \
263
+ ranker.with_same => instance.attributes[ranker.with_same.to_s]
264
+ when Array
265
+ ranker.with_same.each do |column|
266
+ columns << column
267
+ _finder = _finder.where column => instance.attributes[column.to_s]
268
+ end
269
+ end
270
+
271
+ unless new_record?
272
+ _finder = _finder.where.not instance_class.primary_key.to_sym => instance.id
273
+ end
274
+
275
+ _finder.reorder(ranker.column.to_sym => order).select(columns)
276
+ end
277
+ end
278
+
279
+ def current_order
280
+ @current_order ||= begin
281
+ finder.unscope(where: instance_class.primary_key.to_sym).collect { |ordered_instance|
282
+ RankedModel::Ranker::Mapper.new ranker, ordered_instance
283
+ }
284
+ end
285
+ end
286
+
287
+ def current_first
288
+ @current_first ||= begin
289
+ if (ordered_instance = finder.first)
290
+ RankedModel::Ranker::Mapper.new ranker, ordered_instance
291
+ end
292
+ end
293
+ end
294
+
295
+ def current_last
296
+ @current_last ||= begin
297
+ if (ordered_instance = finder.last)
298
+ RankedModel::Ranker::Mapper.new ranker, ordered_instance
299
+ end
300
+ end
301
+ end
302
+
303
+ def rank_taken?
304
+ finder.except(:order).where(ranker.column => rank).exists?
305
+ end
306
+
307
+ def neighbors_at_position _pos
308
+ if _pos > 0
309
+ if (ordered_instances = finder.offset(_pos-1).limit(2).to_a)
310
+ if ordered_instances[1]
311
+ { :lower => RankedModel::Ranker::Mapper.new( ranker, ordered_instances[0] ),
312
+ :upper => RankedModel::Ranker::Mapper.new( ranker, ordered_instances[1] ) }
313
+ elsif ordered_instances[0]
314
+ { :lower => RankedModel::Ranker::Mapper.new( ranker, ordered_instances[0] ) }
315
+ else
316
+ { :lower => current_last }
317
+ end
318
+ end
319
+ else
320
+ if (ordered_instance = finder.first)
321
+ { :upper => RankedModel::Ranker::Mapper.new( ranker, ordered_instance ) }
322
+ else
323
+ {}
324
+ end
325
+ end
326
+ end
327
+
328
+ def find_next_two _rank
329
+ ordered_instances = finder.where(instance_class.arel_table[ranker.column].gt _rank).limit(2)
330
+ if ordered_instances[1]
331
+ { :lower => RankedModel::Ranker::Mapper.new( ranker, ordered_instances[0] ),
332
+ :upper => RankedModel::Ranker::Mapper.new( ranker, ordered_instances[1] ) }
333
+ elsif ordered_instances[0]
334
+ { :lower => RankedModel::Ranker::Mapper.new( ranker, ordered_instances[0] ) }
335
+ else
336
+ {}
337
+ end
338
+ end
339
+
340
+ def find_previous_two _rank
341
+ ordered_instances = finder(:desc).where(instance_class.arel_table[ranker.column].lt _rank).limit(2)
342
+ if ordered_instances[1]
343
+ { :upper => RankedModel::Ranker::Mapper.new( ranker, ordered_instances[0] ),
344
+ :lower => RankedModel::Ranker::Mapper.new( ranker, ordered_instances[1] ) }
345
+ elsif ordered_instances[0]
346
+ { :upper => RankedModel::Ranker::Mapper.new( ranker, ordered_instances[0] ) }
347
+ else
348
+ {}
349
+ end
350
+ end
351
+
352
+ end
353
+
354
+ end
355
+
356
+ end