acts_as_list_neo4j 0.0.1 → 0.0.2
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.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/acts_as_list_neo4j.rb +8 -0
- data/lib/neo4j/acts_as_list.rb +436 -0
- metadata +4 -3
- data/VERSION +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 51bd009a704744c855690ff4be456c9e79b17a43
|
4
|
+
data.tar.gz: 5808e3f7f90457ac8b7330beca053c51cd6b6c54
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c81840bc7330f3f45cc05a45d2ef828967e6452ca46f2a825b56a92dc6f0e35e5fa134bbece1500ca00efa2f18d3ae175a47633197d73be093e1c776a9edd602
|
7
|
+
data.tar.gz: 2a9050c2ae416ec315b252f6de037268bc04e3d89fdde295048b95c27bf50463e8aff677e654a91d9a8cf91572f53e66290e6ad5a8d7f1f3bfe8ff53c3e71acd
|
data/README.md
CHANGED
@@ -67,7 +67,7 @@ item.move(:down) # moves one up (:lower and :down is the same) withi
|
|
67
67
|
item.move(to: position) # moves item to a specific position.
|
68
68
|
item.move(above: other) # moves item above the other item.*
|
69
69
|
item.move(below: other)
|
70
|
-
|
70
|
+
</pre>
|
71
71
|
|
72
72
|
## Running the specs
|
73
73
|
|
@@ -0,0 +1,436 @@
|
|
1
|
+
require 'neo4j'
|
2
|
+
|
3
|
+
module ActsAsList
|
4
|
+
module Neo4j
|
5
|
+
class << self
|
6
|
+
attr_accessor :default_position_column
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.included(klass)
|
10
|
+
klass.extend InitializerMethods
|
11
|
+
key = default_position_column || :position
|
12
|
+
klass.property key, type: Integer
|
13
|
+
klass.acts_as_list column: key.to_s
|
14
|
+
end
|
15
|
+
|
16
|
+
module InitializerMethods
|
17
|
+
def acts_as_list(options = {})
|
18
|
+
configuration = { column: 'position' }
|
19
|
+
configuration.update(options) if options.is_a?(Hash)
|
20
|
+
|
21
|
+
if configuration[:scope]
|
22
|
+
configuration[:scope] = configuration[:scope].to_sym
|
23
|
+
configuration[:scope] = "#{configuration[:scope]}_id".intern if configuration[:scope].to_s !~ /_id$/
|
24
|
+
end
|
25
|
+
|
26
|
+
define_method :position_column do
|
27
|
+
configuration[:column].to_s
|
28
|
+
end
|
29
|
+
|
30
|
+
if !configuration[:scope]
|
31
|
+
define_method :scope_condition do
|
32
|
+
{ "i.#{position_key} <>" => nil }
|
33
|
+
end
|
34
|
+
elsif configuration[:scope].is_a?(Symbol)
|
35
|
+
define_method :scope_condition do
|
36
|
+
{ configuration[:scope] => self[configuration[:scope]] }
|
37
|
+
end
|
38
|
+
else
|
39
|
+
fail ArgumentError, 'acts_as_list must either take a valid :scope option or be in an embedded document and use the parent document as scope'
|
40
|
+
end
|
41
|
+
|
42
|
+
include InstanceMethods
|
43
|
+
include Fields
|
44
|
+
include Triggers
|
45
|
+
extend Fields
|
46
|
+
extend ClassMethods
|
47
|
+
|
48
|
+
before_create :init_list_item
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
module ClassMethods
|
53
|
+
def in_scope
|
54
|
+
where(scope_condition)
|
55
|
+
end
|
56
|
+
|
57
|
+
def move_commands(symbol)
|
58
|
+
case symbol
|
59
|
+
when :symbol
|
60
|
+
[:highest, :top, :lowest, :bottom, :up, :higher, :down, :lower]
|
61
|
+
when :hash
|
62
|
+
[:to, :above, :below]
|
63
|
+
else
|
64
|
+
fail ArgumentError, "no move_commands defined for: #{symbol}"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
module InstanceMethods
|
70
|
+
def move command
|
71
|
+
if command.is_a? Symbol
|
72
|
+
case command
|
73
|
+
when :highest, :top
|
74
|
+
move_to_top
|
75
|
+
when :lowest, :bottom
|
76
|
+
move_to_bottom
|
77
|
+
when :up, :higher
|
78
|
+
move_higher
|
79
|
+
when :down, :lower
|
80
|
+
move_lower
|
81
|
+
else
|
82
|
+
fail ArgumentError, "unknown move command '#{command}', try one of #{self.class.move_commands_available}"
|
83
|
+
end
|
84
|
+
elsif command.is_a? Hash
|
85
|
+
other = command.values.first
|
86
|
+
cmd = command.keys.first
|
87
|
+
case cmd
|
88
|
+
when :to
|
89
|
+
move_to(other)
|
90
|
+
when :above
|
91
|
+
move_above(other)
|
92
|
+
when :below
|
93
|
+
move_below(other)
|
94
|
+
else
|
95
|
+
fail ArgumentError, "Hash command #{cmd.inspect} not valid, must be one of"
|
96
|
+
end
|
97
|
+
else
|
98
|
+
fail ArgumentError, "move command takes either a Symbol or Hash as an argument, not a #{command.class}"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def order_by_position(conditions, extras = [])
|
103
|
+
sub_collection = self_class_all_or_in_collection.where(stringify_conditions(conditions))
|
104
|
+
sub_collection = sub_collection.order_by("i.#{position_key}").pluck(:i)
|
105
|
+
|
106
|
+
sub_collection = sub_collection.order_by(extras) unless extras.empty?
|
107
|
+
|
108
|
+
sub_collection
|
109
|
+
end
|
110
|
+
|
111
|
+
# conditions, { position_column => 1 }
|
112
|
+
def do_decrement(conditions, _options)
|
113
|
+
self_class_all_or_in_collection.where(stringify_conditions(conditions)).pluck(:i).each do |item|
|
114
|
+
item.adjust_position(-1)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def do_increment(conditions, _options)
|
119
|
+
self_class_all_or_in_collection.where(stringify_conditions(conditions)).pluck(:i).each do |item|
|
120
|
+
item.adjust_position(-1)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def less_than_me
|
125
|
+
{ "i.#{position_key} <" => my_position.to_i }
|
126
|
+
end
|
127
|
+
|
128
|
+
def greater_than_me
|
129
|
+
{ "i.#{position_key} >" => my_position.to_i }
|
130
|
+
end
|
131
|
+
|
132
|
+
def insert_at(position = 1)
|
133
|
+
insert_in_list_at(position)
|
134
|
+
end
|
135
|
+
|
136
|
+
def move_to(position = 1)
|
137
|
+
insert_in_list_at(position)
|
138
|
+
end
|
139
|
+
|
140
|
+
def move_below(object)
|
141
|
+
return if self == object
|
142
|
+
if object.my_position > my_position
|
143
|
+
move_to(object.my_position)
|
144
|
+
else
|
145
|
+
move_to(object.my_position + 1)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def move_above(object)
|
150
|
+
return if self == object
|
151
|
+
if object.my_position > my_position
|
152
|
+
move_to(object.my_position - 1)
|
153
|
+
else
|
154
|
+
move_to(object.my_position)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
# Insert the item at the given position (defaults to the top position of 1).
|
159
|
+
def insert_in_list_at(position = 1)
|
160
|
+
insert_at_position(position)
|
161
|
+
end
|
162
|
+
|
163
|
+
# Swap positions with the next lower item, if one exists.
|
164
|
+
def move_lower
|
165
|
+
low_item = lower_item
|
166
|
+
return unless low_item
|
167
|
+
|
168
|
+
low_item.decrement_position
|
169
|
+
increment_position
|
170
|
+
end
|
171
|
+
|
172
|
+
# Swap positions with the next higher item, if one exists.
|
173
|
+
def move_higher
|
174
|
+
high_item = higher_item
|
175
|
+
return unless high_item
|
176
|
+
|
177
|
+
high_item.increment_position
|
178
|
+
decrement_position
|
179
|
+
end
|
180
|
+
|
181
|
+
# Move to the bottom of the list. If the item is already in the list, the items below it have their
|
182
|
+
# position adjusted accordingly.
|
183
|
+
def move_to_bottom
|
184
|
+
return unless in_list?
|
185
|
+
|
186
|
+
decrement_positions_on_lower_items
|
187
|
+
assume_bottom_position
|
188
|
+
end
|
189
|
+
|
190
|
+
# Move to the top of the list. If the item is already in the list, the items above it have their
|
191
|
+
# position adjusted accordingly.
|
192
|
+
def move_to_top
|
193
|
+
return unless in_list?
|
194
|
+
|
195
|
+
increment_positions_on_higher_items
|
196
|
+
assume_top_position
|
197
|
+
end
|
198
|
+
|
199
|
+
# Removes the item from the list.
|
200
|
+
def remove_from_list
|
201
|
+
return unless in_list?
|
202
|
+
decrement_positions_on_lower_items
|
203
|
+
set_my_position nil
|
204
|
+
end
|
205
|
+
|
206
|
+
# Increase the position of this item without adjusting the rest of the list.
|
207
|
+
def increment_position
|
208
|
+
return unless in_list?
|
209
|
+
# self_class_all_or_in_collection.where(:pos => my_position).
|
210
|
+
adjust_position!(1)
|
211
|
+
end
|
212
|
+
|
213
|
+
# Decrease the position of this item without adjusting the rest of the list.
|
214
|
+
def decrement_position
|
215
|
+
return unless in_list?
|
216
|
+
|
217
|
+
# self_class_all_or_in_collection.where(:pos => my_position).
|
218
|
+
adjust_position!(-1)
|
219
|
+
end
|
220
|
+
|
221
|
+
# Return +true+ if this object is the first in the list.
|
222
|
+
def first?
|
223
|
+
return false unless in_list?
|
224
|
+
my_position == 1
|
225
|
+
end
|
226
|
+
|
227
|
+
# Return +true+ if this object is the last in the list.
|
228
|
+
def last?
|
229
|
+
return false unless in_list?
|
230
|
+
bottom_pos = bottom_position_in_list
|
231
|
+
my_position == bottom_pos
|
232
|
+
end
|
233
|
+
|
234
|
+
# Return the next higher item in the list.
|
235
|
+
def higher_item
|
236
|
+
return nil unless in_list?
|
237
|
+
conditions = scope_condition.merge!(less_than_me)
|
238
|
+
order_by_position(conditions).last
|
239
|
+
end
|
240
|
+
|
241
|
+
# Return the next lower item in the list.
|
242
|
+
def lower_item
|
243
|
+
return nil unless in_list?
|
244
|
+
|
245
|
+
conditions = scope_condition.merge!(greater_than_me)
|
246
|
+
order_by_position(conditions).first
|
247
|
+
end
|
248
|
+
|
249
|
+
# Test if this record is in a list
|
250
|
+
def in_list?
|
251
|
+
!my_position.nil?
|
252
|
+
end
|
253
|
+
|
254
|
+
# sorts all items in the list
|
255
|
+
# if two items have same position, the one created more recently goes first
|
256
|
+
def sort
|
257
|
+
conditions = scope_condition
|
258
|
+
list_items = order_by_position(conditions, :created_at.desc).to_a
|
259
|
+
|
260
|
+
list_items.each_with_index do |list_item, index|
|
261
|
+
list_item.set_my_position index + 1
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
private
|
266
|
+
|
267
|
+
def self_class_all_or_in_collection
|
268
|
+
return in_collection.query_as(:i) if self.respond_to?(:in_collection)
|
269
|
+
self.class.all.query_as(:i)
|
270
|
+
end
|
271
|
+
|
272
|
+
def add_to_list_bottom
|
273
|
+
bottom_pos = bottom_position_in_list.to_i
|
274
|
+
set_my_position(bottom_pos + 1)
|
275
|
+
end
|
276
|
+
|
277
|
+
# Overwrite this method to define the scope of the list changes
|
278
|
+
def scope_condition
|
279
|
+
{}
|
280
|
+
end
|
281
|
+
|
282
|
+
# Returns the bottom position number in the list.
|
283
|
+
# bottom_position_in_list # => 2
|
284
|
+
def bottom_position_in_list(_except = nil)
|
285
|
+
item = bottom_item # (except)
|
286
|
+
item ? item.my_position : 0
|
287
|
+
end
|
288
|
+
|
289
|
+
# Returns the bottom item
|
290
|
+
def bottom_item(except = nil)
|
291
|
+
conditions = scope_condition
|
292
|
+
if except
|
293
|
+
conditions.merge!("i.#{position_key} <>" => except.my_position)
|
294
|
+
end
|
295
|
+
|
296
|
+
order_by_position(conditions).last
|
297
|
+
end
|
298
|
+
|
299
|
+
# Forces item to assume the bottom position in the list.
|
300
|
+
def assume_bottom_position
|
301
|
+
pos = bottom_position_in_list(self).to_i + 1
|
302
|
+
set_my_position(pos)
|
303
|
+
end
|
304
|
+
|
305
|
+
# Forces item to assume the top position in the list.
|
306
|
+
def assume_top_position
|
307
|
+
set_my_position(1)
|
308
|
+
end
|
309
|
+
|
310
|
+
# This has the effect of moving all the higher items up one.
|
311
|
+
def decrement_positions_on_higher_items(position)
|
312
|
+
conditions = scope_condition
|
313
|
+
conditions.merge!("i.#{position_key} <" => position)
|
314
|
+
|
315
|
+
decrease_all! self_class_all_or_in_collection.where(stringify_conditions(conditions))
|
316
|
+
end
|
317
|
+
|
318
|
+
# This has the effect of moving all the lower items up one.
|
319
|
+
def decrement_positions_on_lower_items(max_pos = nil)
|
320
|
+
return unless in_list?
|
321
|
+
conditions = scope_condition
|
322
|
+
conditions.merge!(greater_than_me)
|
323
|
+
conditions.merge!("i.#{position_key} <" => max_pos) if max_pos
|
324
|
+
|
325
|
+
decrease_all! self_class_all_or_in_collection.where(stringify_conditions(conditions))
|
326
|
+
end
|
327
|
+
|
328
|
+
# This has the effect of moving all the higher items down one.
|
329
|
+
def increment_positions_on_higher_items(min_pos = nil)
|
330
|
+
return unless in_list?
|
331
|
+
conditions = scope_condition
|
332
|
+
conditions.merge!(less_than_me)
|
333
|
+
conditions.merge!("i.#{position_key} >" => min_pos) if min_pos
|
334
|
+
|
335
|
+
increase_all! self_class_all_or_in_collection.where(stringify_conditions(conditions))
|
336
|
+
end
|
337
|
+
|
338
|
+
def adjust_all!(collection, number)
|
339
|
+
collection.pluck(:i).each do |item|
|
340
|
+
item.adjust_position! number
|
341
|
+
end
|
342
|
+
end
|
343
|
+
|
344
|
+
def increase_all!(collection)
|
345
|
+
adjust_all! collection, 1
|
346
|
+
end
|
347
|
+
|
348
|
+
def decrease_all!(collection)
|
349
|
+
adjust_all! collection, -1
|
350
|
+
end
|
351
|
+
|
352
|
+
# This has the effect of moving all the lower items down one.
|
353
|
+
def increment_positions_on_lower_items(position)
|
354
|
+
conditions = scope_condition
|
355
|
+
conditions.merge!("i.#{position_key} >=" => position)
|
356
|
+
|
357
|
+
increase_all! self_class_all_or_in_collection.where(stringify_conditions(conditions))
|
358
|
+
end
|
359
|
+
|
360
|
+
# Increments position (<tt>position_column</tt>) of all items in the list.
|
361
|
+
def increment_positions_on_all_items
|
362
|
+
conditions = scope_condition
|
363
|
+
increase_all! self_class_all_or_in_collection.where(stringify_conditions(conditions))
|
364
|
+
end
|
365
|
+
|
366
|
+
alias_method :add_to_list_top, :increment_positions_on_all_items
|
367
|
+
|
368
|
+
def insert_at_position(position)
|
369
|
+
position = [position, 1].max
|
370
|
+
remove_from_list
|
371
|
+
increment_positions_on_lower_items(position)
|
372
|
+
set_my_position(position)
|
373
|
+
end
|
374
|
+
|
375
|
+
def stringify_conditions(conditions)
|
376
|
+
return nil if conditions.empty?
|
377
|
+
conditions.reject { |_key, value| value.nil? }.map { |key, value| "#{key} #{value}" }.join(' and ')
|
378
|
+
end
|
379
|
+
end
|
380
|
+
|
381
|
+
module Triggers
|
382
|
+
def after_parentize
|
383
|
+
# should register on root element to be called when root is saved first time!?
|
384
|
+
end
|
385
|
+
|
386
|
+
def init_list_item
|
387
|
+
add_to_list_bottom unless in_list?
|
388
|
+
end
|
389
|
+
end
|
390
|
+
|
391
|
+
module Fields
|
392
|
+
def my_position
|
393
|
+
send position_column
|
394
|
+
end
|
395
|
+
|
396
|
+
def set_my_position(new_position)
|
397
|
+
return if new_position == my_position
|
398
|
+
if id
|
399
|
+
update_attributes! position_column => new_position
|
400
|
+
else
|
401
|
+
send "#{position_column}=", new_position
|
402
|
+
end
|
403
|
+
end
|
404
|
+
|
405
|
+
def ==(other)
|
406
|
+
return true if other.equal?(self)
|
407
|
+
return true if other.instance_of?(self.class) && other.respond_to?('id') && other.id == id
|
408
|
+
false
|
409
|
+
end
|
410
|
+
|
411
|
+
# Overwrites default comparer to return comparison index value based on defined position
|
412
|
+
def <=>(other)
|
413
|
+
my_position <=> other.my_position
|
414
|
+
end
|
415
|
+
|
416
|
+
def position_key
|
417
|
+
position_column.to_sym
|
418
|
+
end
|
419
|
+
|
420
|
+
def adjust_position!(number)
|
421
|
+
adjust_position(number)
|
422
|
+
save!
|
423
|
+
end
|
424
|
+
|
425
|
+
def adjust_position(number)
|
426
|
+
set_my_position(my_position + number)
|
427
|
+
end
|
428
|
+
end
|
429
|
+
end
|
430
|
+
end
|
431
|
+
|
432
|
+
class Array
|
433
|
+
def init_list!
|
434
|
+
each(&:init_list_item!)
|
435
|
+
end
|
436
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: acts_as_list_neo4j
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stayman Hou
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-07-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: neo4j
|
@@ -148,7 +148,8 @@ extra_rdoc_files:
|
|
148
148
|
files:
|
149
149
|
- LICENSE.md
|
150
150
|
- README.md
|
151
|
-
-
|
151
|
+
- lib/acts_as_list_neo4j.rb
|
152
|
+
- lib/neo4j/acts_as_list.rb
|
152
153
|
homepage: http://github.com/rails/acts_as_list
|
153
154
|
licenses:
|
154
155
|
- MIT
|
data/VERSION
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
0.0.1
|