acts_as_list 0.2.0 → 0.4.0
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 +7 -0
- data/.travis.yml +10 -1
- data/Gemfile +9 -0
- data/MIT-LICENSE +19 -0
- data/README.md +4 -1
- data/Rakefile +15 -9
- data/acts_as_list.gemspec +2 -3
- data/gemfiles/rails3/Gemfile +17 -0
- data/gemfiles/rails4/Gemfile +18 -0
- data/lib/acts_as_list/active_record/acts/list.rb +70 -29
- data/lib/acts_as_list/version.rb +1 -1
- data/test/helper.rb +1 -1
- data/test/shared.rb +1 -0
- data/test/shared_array_scope_list.rb +62 -62
- data/test/shared_list.rb +96 -76
- data/test/shared_list_sub.rb +35 -35
- data/test/shared_no_addition.rb +25 -0
- data/test/shared_top_addition.rb +29 -29
- data/test/shared_zero_based.rb +28 -23
- data/test/test_list.rb +148 -112
- metadata +55 -98
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: d5cbf688ac985c43f61b4c0669030f5b6f6c6caa
|
|
4
|
+
data.tar.gz: aef8fc0d40ed0ee55bf73ff2b7989e14e9c6572e
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: de7f8dd3123cb1bf1fd5837517c221d8a6682207c3a75ac99a7457782b5ebf6d3fa995ee12664674cc7dfacaca6bd7e5ffaa484407502856aa8e9932ff066746
|
|
7
|
+
data.tar.gz: 20d069cc6a4420dd3dd6073f12ab8940cf2bb3c1003bd71faca489ddefe780349159696cd12ef37e65578ac796c0d4686af3c231cff832f3eb2b2a3306f2da62
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
source "http://rubygems.org"
|
|
2
2
|
|
|
3
|
+
gem 'sqlite3', :platforms => [:ruby]
|
|
4
|
+
gem 'activerecord-jdbcsqlite3-adapter', :platforms => [:jruby]
|
|
5
|
+
|
|
6
|
+
platforms :rbx do
|
|
7
|
+
gem 'rubysl', '~> 2.0'
|
|
8
|
+
gem 'rubinius-developer_tools'
|
|
9
|
+
gem 'rubysl-test-unit'
|
|
10
|
+
end
|
|
11
|
+
|
|
3
12
|
# Specify your gem's dependencies in acts_as_list-rails3.gemspec
|
|
4
13
|
gemspec
|
|
5
14
|
|
data/MIT-LICENSE
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Copyright (c) 2007 David Heinemeier Hansson
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
5
|
+
in the Software without restriction, including without limitation the rights
|
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
8
|
+
furnished to do so, subject to the following conditions:
|
|
9
|
+
|
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
|
11
|
+
all copies or substantial portions of the Software.
|
|
12
|
+
|
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
19
|
+
THE SOFTWARE.
|
data/README.md
CHANGED
|
@@ -25,7 +25,7 @@ After that you can use `acts_as_list` method in the model:
|
|
|
25
25
|
|
|
26
26
|
```ruby
|
|
27
27
|
class TodoList < ActiveRecord::Base
|
|
28
|
-
has_many :todo_items, order
|
|
28
|
+
has_many :todo_items, -> { order("position ASC") }
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
class TodoItem < ActiveRecord::Base
|
|
@@ -82,6 +82,9 @@ All versions `0.1.5` onwards require Rails 3.0.x and higher.
|
|
|
82
82
|
## Build Status
|
|
83
83
|
[](https://secure.travis-ci.org/swanandp/acts_as_list)
|
|
84
84
|
|
|
85
|
+
## Workflow Status
|
|
86
|
+
[](http://waffle.io/swanandp/acts_as_list)
|
|
87
|
+
|
|
85
88
|
## Roadmap
|
|
86
89
|
|
|
87
90
|
1. Sort based feature
|
data/Rakefile
CHANGED
|
@@ -15,15 +15,21 @@ Rake::TestTask.new(:test) do |t|
|
|
|
15
15
|
t.verbose = false
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
begin
|
|
19
|
+
# Run the rdoc task to generate rdocs for this gem
|
|
20
|
+
require 'rdoc/task'
|
|
21
|
+
RDoc::Task.new do |rdoc|
|
|
22
|
+
require "acts_as_list/version"
|
|
23
|
+
version = ActiveRecord::Acts::List::VERSION
|
|
23
24
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
rdoc.rdoc_dir = 'rdoc'
|
|
26
|
+
rdoc.title = "acts_as_list-rails3 #{version}"
|
|
27
|
+
rdoc.rdoc_files.include('README*')
|
|
28
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
29
|
+
end
|
|
30
|
+
rescue LoadError
|
|
31
|
+
puts 'RDocTask is not supported on this platform.'
|
|
32
|
+
rescue StandardError
|
|
33
|
+
puts 'RDocTask is not supported on this platform.'
|
|
28
34
|
end
|
|
29
35
|
|
data/acts_as_list.gemspec
CHANGED
|
@@ -13,8 +13,9 @@ Gem::Specification.new do |s|
|
|
|
13
13
|
s.homepage = 'http://github.com/swanandp/acts_as_list'
|
|
14
14
|
s.summary = %q{A gem allowing a active_record model to act_as_list.}
|
|
15
15
|
s.description = %q{This "acts_as" extension provides the capabilities for sorting and reordering a number of objects in a list. The class that has this specified needs to have a "position" column defined as an integer on the mapped database table.}
|
|
16
|
+
s.license = 'MIT'
|
|
16
17
|
s.rubyforge_project = 'acts_as_list'
|
|
17
|
-
|
|
18
|
+
s.required_ruby_version = '>= 1.9.2'
|
|
18
19
|
|
|
19
20
|
# Load Paths...
|
|
20
21
|
s.files = `git ls-files`.split("\n")
|
|
@@ -26,6 +27,4 @@ Gem::Specification.new do |s|
|
|
|
26
27
|
# Dependencies (installed via 'bundle install')...
|
|
27
28
|
s.add_dependency("activerecord", [">= 3.0"])
|
|
28
29
|
s.add_development_dependency("bundler", [">= 1.0.0"])
|
|
29
|
-
s.add_development_dependency("rdoc")
|
|
30
|
-
s.add_development_dependency("sqlite3")
|
|
31
30
|
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
source "https://rubygems.org"
|
|
2
|
+
|
|
3
|
+
gem 'sqlite3', :platforms => [:ruby]
|
|
4
|
+
gem 'activerecord-jdbcsqlite3-adapter', :platforms => [:jruby]
|
|
5
|
+
|
|
6
|
+
platforms :rbx do
|
|
7
|
+
gem 'rubysl', '~> 2.0'
|
|
8
|
+
gem 'rubinius-developer_tools'
|
|
9
|
+
gem 'rubysl-test-unit'
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
gem 'activerecord', '>= 3.0', '< 4'
|
|
13
|
+
|
|
14
|
+
# Specify your gem's dependencies in acts_as_list.gemspec
|
|
15
|
+
gemspec :path => File.join('..', '..')
|
|
16
|
+
|
|
17
|
+
gem 'rake'
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
source "https://rubygems.org"
|
|
2
|
+
|
|
3
|
+
gem 'sqlite3', :platforms => [:ruby]
|
|
4
|
+
gem 'activerecord-jdbcsqlite3-adapter', :platforms => [:jruby]
|
|
5
|
+
|
|
6
|
+
platforms :rbx do
|
|
7
|
+
gem 'rubysl', '~> 2.0'
|
|
8
|
+
gem 'rubinius-developer_tools'
|
|
9
|
+
gem 'rubysl-test-unit'
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
gem 'activerecord', '>= 4.0.0', '< 5'
|
|
14
|
+
|
|
15
|
+
# Specify your gem's dependencies in acts_as_list.gemspec
|
|
16
|
+
gemspec :path => File.join('..', '..')
|
|
17
|
+
|
|
18
|
+
gem 'rake'
|
|
@@ -12,12 +12,12 @@ module ActiveRecord
|
|
|
12
12
|
# Todo list example:
|
|
13
13
|
#
|
|
14
14
|
# class TodoList < ActiveRecord::Base
|
|
15
|
-
# has_many :todo_items, :
|
|
15
|
+
# has_many :todo_items, order: "position"
|
|
16
16
|
# end
|
|
17
17
|
#
|
|
18
18
|
# class TodoItem < ActiveRecord::Base
|
|
19
19
|
# belongs_to :todo_list
|
|
20
|
-
# acts_as_list :
|
|
20
|
+
# acts_as_list scope: :todo_list
|
|
21
21
|
# end
|
|
22
22
|
#
|
|
23
23
|
# todo_list.first.move_to_bottom
|
|
@@ -29,33 +29,51 @@ module ActiveRecord
|
|
|
29
29
|
# * +scope+ - restricts what is to be considered a list. Given a symbol, it'll attach <tt>_id</tt>
|
|
30
30
|
# (if it hasn't already been added) and use that as the foreign key restriction. It's also possible
|
|
31
31
|
# to give it an entire string that is interpolated if you need a tighter scope than just a foreign key.
|
|
32
|
-
# Example: <tt>acts_as_list :
|
|
32
|
+
# Example: <tt>acts_as_list scope: 'todo_list_id = #{todo_list_id} AND completed = 0'</tt>
|
|
33
33
|
# * +top_of_list+ - defines the integer used for the top of the list. Defaults to 1. Use 0 to make the collection
|
|
34
34
|
# act more like an array in its indexing.
|
|
35
35
|
# * +add_new_at+ - specifies whether objects get added to the :top or :bottom of the list. (default: +bottom+)
|
|
36
|
+
# `nil` will result in new items not being added to the list on create
|
|
36
37
|
def acts_as_list(options = {})
|
|
37
|
-
configuration = { :
|
|
38
|
+
configuration = { column: "position", scope: "1 = 1", top_of_list: 1, add_new_at: :bottom}
|
|
38
39
|
configuration.update(options) if options.is_a?(Hash)
|
|
39
40
|
|
|
40
41
|
configuration[:scope] = "#{configuration[:scope]}_id".intern if configuration[:scope].is_a?(Symbol) && configuration[:scope].to_s !~ /_id$/
|
|
41
42
|
|
|
42
43
|
if configuration[:scope].is_a?(Symbol)
|
|
43
|
-
|
|
44
|
+
scope_methods = %(
|
|
44
45
|
def scope_condition
|
|
45
46
|
self.class.send(:sanitize_sql_hash_for_conditions, { :#{configuration[:scope].to_s} => send(:#{configuration[:scope].to_s}) })
|
|
46
47
|
end
|
|
48
|
+
|
|
49
|
+
def scope_changed?
|
|
50
|
+
changes.include?(scope_name.to_s)
|
|
51
|
+
end
|
|
47
52
|
)
|
|
48
53
|
elsif configuration[:scope].is_a?(Array)
|
|
49
|
-
|
|
50
|
-
def
|
|
51
|
-
|
|
54
|
+
scope_methods = %(
|
|
55
|
+
def attrs
|
|
56
|
+
%w(#{configuration[:scope].join(" ")}).inject({}) do |memo,column|
|
|
52
57
|
memo[column.intern] = send(column.intern); memo
|
|
53
58
|
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def scope_changed?
|
|
62
|
+
(attrs.keys & changes.keys.map(&:to_sym)).any?
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def scope_condition
|
|
54
66
|
self.class.send(:sanitize_sql_hash_for_conditions, attrs)
|
|
55
67
|
end
|
|
56
68
|
)
|
|
57
69
|
else
|
|
58
|
-
|
|
70
|
+
scope_methods = %(
|
|
71
|
+
def scope_condition
|
|
72
|
+
"#{configuration[:scope]}"
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def scope_changed?() false end
|
|
76
|
+
)
|
|
59
77
|
end
|
|
60
78
|
|
|
61
79
|
class_eval <<-EOV
|
|
@@ -81,7 +99,7 @@ module ActiveRecord
|
|
|
81
99
|
'#{configuration[:add_new_at]}'
|
|
82
100
|
end
|
|
83
101
|
|
|
84
|
-
#{
|
|
102
|
+
#{scope_methods}
|
|
85
103
|
|
|
86
104
|
# only add to attr_accessible
|
|
87
105
|
# if the class has some mass_assignment_protection
|
|
@@ -92,10 +110,17 @@ module ActiveRecord
|
|
|
92
110
|
|
|
93
111
|
before_destroy :reload_position
|
|
94
112
|
after_destroy :decrement_positions_on_lower_items
|
|
95
|
-
before_create :add_to_list_#{configuration[:add_new_at]}
|
|
96
|
-
after_update :update_positions
|
|
97
113
|
before_update :check_scope
|
|
114
|
+
after_update :update_positions
|
|
115
|
+
before_validation :check_top_position
|
|
116
|
+
|
|
117
|
+
scope :in_list, lambda { where("#{table_name}.#{configuration[:column]} IS NOT NULL") }
|
|
98
118
|
EOV
|
|
119
|
+
|
|
120
|
+
if configuration[:add_new_at].present?
|
|
121
|
+
self.send(:before_create, "add_to_list_#{configuration[:add_new_at]}")
|
|
122
|
+
end
|
|
123
|
+
|
|
99
124
|
end
|
|
100
125
|
end
|
|
101
126
|
|
|
@@ -157,6 +182,12 @@ module ActiveRecord
|
|
|
157
182
|
end
|
|
158
183
|
end
|
|
159
184
|
|
|
185
|
+
# Move the item within scope
|
|
186
|
+
def move_within_scope(scope_id)
|
|
187
|
+
send("#{scope_name}=", scope_id)
|
|
188
|
+
save!
|
|
189
|
+
end
|
|
190
|
+
|
|
160
191
|
# Increase the position of this item without adjusting the rest of the list.
|
|
161
192
|
def increment_position
|
|
162
193
|
return unless in_list?
|
|
@@ -184,10 +215,9 @@ module ActiveRecord
|
|
|
184
215
|
# Return the next higher item in the list.
|
|
185
216
|
def higher_item
|
|
186
217
|
return nil unless in_list?
|
|
187
|
-
acts_as_list_class.unscoped.
|
|
188
|
-
"#{scope_condition} AND #{position_column} < #{(send(position_column).to_i).to_s}"
|
|
189
|
-
|
|
190
|
-
)
|
|
218
|
+
acts_as_list_class.unscoped.
|
|
219
|
+
where("#{scope_condition} AND #{position_column} < #{(send(position_column).to_i).to_s}").
|
|
220
|
+
order("#{acts_as_list_class.table_name}.#{position_column} DESC").first
|
|
191
221
|
end
|
|
192
222
|
|
|
193
223
|
# Return the next n higher items in the list
|
|
@@ -205,10 +235,9 @@ module ActiveRecord
|
|
|
205
235
|
# Return the next lower item in the list.
|
|
206
236
|
def lower_item
|
|
207
237
|
return nil unless in_list?
|
|
208
|
-
acts_as_list_class.unscoped.
|
|
209
|
-
"#{scope_condition} AND #{position_column} > #{(send(position_column).to_i).to_s}"
|
|
210
|
-
|
|
211
|
-
)
|
|
238
|
+
acts_as_list_class.unscoped.
|
|
239
|
+
where("#{scope_condition} AND #{position_column} > #{(send(position_column).to_i).to_s}").
|
|
240
|
+
order("#{acts_as_list_class.table_name}.#{position_column} ASC").first
|
|
212
241
|
end
|
|
213
242
|
|
|
214
243
|
# Return the next n lower items in the list
|
|
@@ -278,8 +307,8 @@ module ActiveRecord
|
|
|
278
307
|
# Returns the bottom item
|
|
279
308
|
def bottom_item(except = nil)
|
|
280
309
|
conditions = scope_condition
|
|
281
|
-
conditions = "#{conditions} AND #{self.class.primary_key} != #{except.id}" if except
|
|
282
|
-
acts_as_list_class.unscoped.where(conditions).order("#{acts_as_list_class.table_name}.#{position_column} DESC").first
|
|
310
|
+
conditions = "#{conditions} AND #{self.class.primary_key} != '#{except.id}'" if except
|
|
311
|
+
acts_as_list_class.unscoped.in_list.where(conditions).order("#{acts_as_list_class.table_name}.#{position_column} DESC").first
|
|
283
312
|
end
|
|
284
313
|
|
|
285
314
|
# Forces item to assume the bottom position in the list.
|
|
@@ -343,7 +372,7 @@ module ActiveRecord
|
|
|
343
372
|
# Reorders intermediate items to support moving an item from old_position to new_position.
|
|
344
373
|
def shuffle_positions_on_intermediate_items(old_position, new_position, avoid_id = nil)
|
|
345
374
|
return if old_position == new_position
|
|
346
|
-
avoid_id_condition = avoid_id ? " AND #{self.class.primary_key} != #{avoid_id}" : ''
|
|
375
|
+
avoid_id_condition = avoid_id ? " AND #{self.class.primary_key} != '#{avoid_id}'" : ''
|
|
347
376
|
if old_position < new_position
|
|
348
377
|
# Decrement position of intermediate items
|
|
349
378
|
#
|
|
@@ -368,6 +397,7 @@ module ActiveRecord
|
|
|
368
397
|
end
|
|
369
398
|
|
|
370
399
|
def insert_at_position(position)
|
|
400
|
+
return set_list_position(position) if new_record?
|
|
371
401
|
if in_list?
|
|
372
402
|
old_position = send(position_column).to_i
|
|
373
403
|
return if position == old_position
|
|
@@ -390,17 +420,22 @@ module ActiveRecord
|
|
|
390
420
|
def update_positions
|
|
391
421
|
old_position = send("#{position_column}_was").to_i
|
|
392
422
|
new_position = send(position_column).to_i
|
|
423
|
+
|
|
393
424
|
return unless acts_as_list_class.unscoped.where("#{scope_condition} AND #{position_column} = #{new_position}").count > 1
|
|
394
425
|
shuffle_positions_on_intermediate_items old_position, new_position, id
|
|
395
426
|
end
|
|
396
427
|
|
|
428
|
+
# Temporarily swap changes attributes with current attributes
|
|
429
|
+
def swap_changed_attributes
|
|
430
|
+
@changed_attributes.each { |k, _| @changed_attributes[k], self[k] =
|
|
431
|
+
self[k], @changed_attributes[k] }
|
|
432
|
+
end
|
|
433
|
+
|
|
397
434
|
def check_scope
|
|
398
|
-
if
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
send("decrement_positions_on_lower_items")
|
|
403
|
-
self["#{scope_name}"] = new_scope_id
|
|
435
|
+
if scope_changed?
|
|
436
|
+
swap_changed_attributes
|
|
437
|
+
send('decrement_positions_on_lower_items') if lower_item
|
|
438
|
+
swap_changed_attributes
|
|
404
439
|
send("add_to_list_#{add_new_at}")
|
|
405
440
|
end
|
|
406
441
|
end
|
|
@@ -408,6 +443,12 @@ module ActiveRecord
|
|
|
408
443
|
def reload_position
|
|
409
444
|
self.reload
|
|
410
445
|
end
|
|
446
|
+
|
|
447
|
+
def check_top_position
|
|
448
|
+
if send(position_column) && send(position_column) < acts_as_list_top
|
|
449
|
+
self[position_column] = acts_as_list_top
|
|
450
|
+
end
|
|
451
|
+
end
|
|
411
452
|
end
|
|
412
453
|
end
|
|
413
454
|
end
|
data/lib/acts_as_list/version.rb
CHANGED
data/test/helper.rb
CHANGED
|
@@ -7,8 +7,8 @@ rescue Bundler::BundlerError => e
|
|
|
7
7
|
$stderr.puts "Run `bundle install` to install missing gems"
|
|
8
8
|
exit e.status_code
|
|
9
9
|
end
|
|
10
|
-
require 'test/unit'
|
|
11
10
|
require 'active_record'
|
|
11
|
+
require 'minitest/autorun'
|
|
12
12
|
require "#{File.dirname(__FILE__)}/../init"
|
|
13
13
|
|
|
14
14
|
require 'shared'
|
data/test/shared.rb
CHANGED
|
@@ -1,87 +1,87 @@
|
|
|
1
1
|
module Shared
|
|
2
2
|
module ArrayScopeList
|
|
3
3
|
def setup
|
|
4
|
-
(1..4).each { |counter| ArrayScopeListMixin.create! :
|
|
5
|
-
(1..4).each { |counter| ArrayScopeListMixin.create! :
|
|
4
|
+
(1..4).each { |counter| ArrayScopeListMixin.create! pos: counter, parent_id: 5, parent_type: 'ParentClass' }
|
|
5
|
+
(1..4).each { |counter| ArrayScopeListMixin.create! pos: counter, parent_id: 6, parent_type: 'ParentClass' }
|
|
6
6
|
end
|
|
7
7
|
|
|
8
8
|
def test_reordering
|
|
9
|
-
assert_equal [1, 2, 3, 4], ArrayScopeListMixin.
|
|
9
|
+
assert_equal [1, 2, 3, 4], ArrayScopeListMixin.where(parent_id: 5, parent_type: 'ParentClass').order('pos').map(&:id)
|
|
10
10
|
|
|
11
|
-
ArrayScopeListMixin.
|
|
12
|
-
assert_equal [1, 3, 2, 4], ArrayScopeListMixin.
|
|
11
|
+
ArrayScopeListMixin.where(id: 2).first.move_lower
|
|
12
|
+
assert_equal [1, 3, 2, 4], ArrayScopeListMixin.where(parent_id: 5, parent_type: 'ParentClass').order('pos').map(&:id)
|
|
13
13
|
|
|
14
|
-
ArrayScopeListMixin.
|
|
15
|
-
assert_equal [1, 2, 3, 4], ArrayScopeListMixin.
|
|
14
|
+
ArrayScopeListMixin.where(id: 2).first.move_higher
|
|
15
|
+
assert_equal [1, 2, 3, 4], ArrayScopeListMixin.where(parent_id: 5, parent_type: 'ParentClass').order('pos').map(&:id)
|
|
16
16
|
|
|
17
|
-
ArrayScopeListMixin.
|
|
18
|
-
assert_equal [2, 3, 4, 1], ArrayScopeListMixin.
|
|
17
|
+
ArrayScopeListMixin.where(id: 1).first.move_to_bottom
|
|
18
|
+
assert_equal [2, 3, 4, 1], ArrayScopeListMixin.where(parent_id: 5, parent_type: 'ParentClass').order('pos').map(&:id)
|
|
19
19
|
|
|
20
|
-
ArrayScopeListMixin.
|
|
21
|
-
assert_equal [1, 2, 3, 4], ArrayScopeListMixin.
|
|
20
|
+
ArrayScopeListMixin.where(id: 1).first.move_to_top
|
|
21
|
+
assert_equal [1, 2, 3, 4], ArrayScopeListMixin.where(parent_id: 5, parent_type: 'ParentClass').order('pos').map(&:id)
|
|
22
22
|
|
|
23
|
-
ArrayScopeListMixin.
|
|
24
|
-
assert_equal [1, 3, 4, 2], ArrayScopeListMixin.
|
|
23
|
+
ArrayScopeListMixin.where(id: 2).first.move_to_bottom
|
|
24
|
+
assert_equal [1, 3, 4, 2], ArrayScopeListMixin.where(parent_id: 5, parent_type: 'ParentClass').order('pos').map(&:id)
|
|
25
25
|
|
|
26
|
-
ArrayScopeListMixin.
|
|
27
|
-
assert_equal [4, 1, 3, 2], ArrayScopeListMixin.
|
|
26
|
+
ArrayScopeListMixin.where(id: 4).first.move_to_top
|
|
27
|
+
assert_equal [4, 1, 3, 2], ArrayScopeListMixin.where(parent_id: 5, parent_type: 'ParentClass').order('pos').map(&:id)
|
|
28
28
|
|
|
29
|
-
ArrayScopeListMixin.
|
|
30
|
-
assert_equal [1, 3, 2, 4], ArrayScopeListMixin.
|
|
31
|
-
assert_equal [1, 2, 3, 4], ArrayScopeListMixin.
|
|
29
|
+
ArrayScopeListMixin.where(id: 4).first.insert_at(4)
|
|
30
|
+
assert_equal [1, 3, 2, 4], ArrayScopeListMixin.where(parent_id: 5, parent_type: 'ParentClass').order('pos').map(&:id)
|
|
31
|
+
assert_equal [1, 2, 3, 4], ArrayScopeListMixin.where(parent_id: 5, parent_type: 'ParentClass').order('pos').map(&:pos)
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
def test_move_to_bottom_with_next_to_last_item
|
|
35
|
-
assert_equal [1, 2, 3, 4], ArrayScopeListMixin.
|
|
36
|
-
ArrayScopeListMixin.
|
|
37
|
-
assert_equal [1, 2, 4, 3], ArrayScopeListMixin.
|
|
35
|
+
assert_equal [1, 2, 3, 4], ArrayScopeListMixin.where(parent_id: 5, parent_type: 'ParentClass').order('pos').map(&:id)
|
|
36
|
+
ArrayScopeListMixin.where(id: 3).first.move_to_bottom
|
|
37
|
+
assert_equal [1, 2, 4, 3], ArrayScopeListMixin.where(parent_id: 5, parent_type: 'ParentClass').order('pos').map(&:id)
|
|
38
38
|
end
|
|
39
39
|
|
|
40
40
|
def test_next_prev
|
|
41
|
-
assert_equal ArrayScopeListMixin.
|
|
42
|
-
assert_nil ArrayScopeListMixin.
|
|
43
|
-
assert_equal ArrayScopeListMixin.
|
|
44
|
-
assert_nil ArrayScopeListMixin.
|
|
41
|
+
assert_equal ArrayScopeListMixin.where(id: 2).first, ArrayScopeListMixin.where(id: 1).first.lower_item
|
|
42
|
+
assert_nil ArrayScopeListMixin.where(id: 1).first.higher_item
|
|
43
|
+
assert_equal ArrayScopeListMixin.where(id: 3).first, ArrayScopeListMixin.where(id: 4).first.higher_item
|
|
44
|
+
assert_nil ArrayScopeListMixin.where(id: 4).first.lower_item
|
|
45
45
|
end
|
|
46
46
|
|
|
47
47
|
def test_injection
|
|
48
|
-
item = ArrayScopeListMixin.new(:
|
|
48
|
+
item = ArrayScopeListMixin.new(parent_id: 1, parent_type: 'ParentClass')
|
|
49
49
|
assert_equal "pos", item.position_column
|
|
50
50
|
end
|
|
51
51
|
|
|
52
52
|
def test_insert
|
|
53
|
-
new = ArrayScopeListMixin.create(:
|
|
53
|
+
new = ArrayScopeListMixin.create(parent_id: 20, parent_type: 'ParentClass')
|
|
54
54
|
assert_equal 1, new.pos
|
|
55
55
|
assert new.first?
|
|
56
56
|
assert new.last?
|
|
57
57
|
|
|
58
|
-
new = ArrayScopeListMixin.create(:
|
|
58
|
+
new = ArrayScopeListMixin.create(parent_id: 20, parent_type: 'ParentClass')
|
|
59
59
|
assert_equal 2, new.pos
|
|
60
60
|
assert !new.first?
|
|
61
61
|
assert new.last?
|
|
62
62
|
|
|
63
|
-
new = ArrayScopeListMixin.create(:
|
|
63
|
+
new = ArrayScopeListMixin.create(parent_id: 20, parent_type: 'ParentClass')
|
|
64
64
|
assert_equal 3, new.pos
|
|
65
65
|
assert !new.first?
|
|
66
66
|
assert new.last?
|
|
67
67
|
|
|
68
|
-
new = ArrayScopeListMixin.create(:
|
|
68
|
+
new = ArrayScopeListMixin.create(parent_id: 0, parent_type: 'ParentClass')
|
|
69
69
|
assert_equal 1, new.pos
|
|
70
70
|
assert new.first?
|
|
71
71
|
assert new.last?
|
|
72
72
|
end
|
|
73
73
|
|
|
74
74
|
def test_insert_at
|
|
75
|
-
new = ArrayScopeListMixin.create(:
|
|
75
|
+
new = ArrayScopeListMixin.create(parent_id: 20, parent_type: 'ParentClass')
|
|
76
76
|
assert_equal 1, new.pos
|
|
77
77
|
|
|
78
|
-
new = ArrayScopeListMixin.create(:
|
|
78
|
+
new = ArrayScopeListMixin.create(parent_id: 20, parent_type: 'ParentClass')
|
|
79
79
|
assert_equal 2, new.pos
|
|
80
80
|
|
|
81
|
-
new = ArrayScopeListMixin.create(:
|
|
81
|
+
new = ArrayScopeListMixin.create(parent_id: 20, parent_type: 'ParentClass')
|
|
82
82
|
assert_equal 3, new.pos
|
|
83
83
|
|
|
84
|
-
new4 = ArrayScopeListMixin.create(:
|
|
84
|
+
new4 = ArrayScopeListMixin.create(parent_id: 20, parent_type: 'ParentClass')
|
|
85
85
|
assert_equal 4, new4.pos
|
|
86
86
|
|
|
87
87
|
new4.insert_at(3)
|
|
@@ -96,7 +96,7 @@ module Shared
|
|
|
96
96
|
new4.reload
|
|
97
97
|
assert_equal 4, new4.pos
|
|
98
98
|
|
|
99
|
-
new5 = ArrayScopeListMixin.create(:
|
|
99
|
+
new5 = ArrayScopeListMixin.create(parent_id: 20, parent_type: 'ParentClass')
|
|
100
100
|
assert_equal 5, new5.pos
|
|
101
101
|
|
|
102
102
|
new5.insert_at(1)
|
|
@@ -107,54 +107,54 @@ module Shared
|
|
|
107
107
|
end
|
|
108
108
|
|
|
109
109
|
def test_delete_middle
|
|
110
|
-
assert_equal [1, 2, 3, 4], ArrayScopeListMixin.
|
|
110
|
+
assert_equal [1, 2, 3, 4], ArrayScopeListMixin.where(parent_id: 5, parent_type: 'ParentClass').order('pos').map(&:id)
|
|
111
111
|
|
|
112
|
-
ArrayScopeListMixin.
|
|
112
|
+
ArrayScopeListMixin.where(id: 2).first.destroy
|
|
113
113
|
|
|
114
|
-
assert_equal [1, 3, 4], ArrayScopeListMixin.
|
|
114
|
+
assert_equal [1, 3, 4], ArrayScopeListMixin.where(parent_id: 5, parent_type: 'ParentClass').order('pos').map(&:id)
|
|
115
115
|
|
|
116
|
-
assert_equal 1, ArrayScopeListMixin.
|
|
117
|
-
assert_equal 2, ArrayScopeListMixin.
|
|
118
|
-
assert_equal 3, ArrayScopeListMixin.
|
|
116
|
+
assert_equal 1, ArrayScopeListMixin.where(id: 1).first.pos
|
|
117
|
+
assert_equal 2, ArrayScopeListMixin.where(id: 3).first.pos
|
|
118
|
+
assert_equal 3, ArrayScopeListMixin.where(id: 4).first.pos
|
|
119
119
|
|
|
120
|
-
ArrayScopeListMixin.
|
|
120
|
+
ArrayScopeListMixin.where(id: 1).first.destroy
|
|
121
121
|
|
|
122
|
-
assert_equal [3, 4], ArrayScopeListMixin.
|
|
122
|
+
assert_equal [3, 4], ArrayScopeListMixin.where(parent_id: 5, parent_type: 'ParentClass').order('pos').map(&:id)
|
|
123
123
|
|
|
124
|
-
assert_equal 1, ArrayScopeListMixin.
|
|
125
|
-
assert_equal 2, ArrayScopeListMixin.
|
|
124
|
+
assert_equal 1, ArrayScopeListMixin.where(id: 3).first.pos
|
|
125
|
+
assert_equal 2, ArrayScopeListMixin.where(id: 4).first.pos
|
|
126
126
|
end
|
|
127
127
|
|
|
128
128
|
def test_remove_from_list_should_then_fail_in_list?
|
|
129
|
-
assert_equal true, ArrayScopeListMixin.
|
|
130
|
-
ArrayScopeListMixin.
|
|
131
|
-
assert_equal false, ArrayScopeListMixin.
|
|
129
|
+
assert_equal true, ArrayScopeListMixin.where(id: 1).first.in_list?
|
|
130
|
+
ArrayScopeListMixin.where(id: 1).first.remove_from_list
|
|
131
|
+
assert_equal false, ArrayScopeListMixin.where(id: 1).first.in_list?
|
|
132
132
|
end
|
|
133
133
|
|
|
134
134
|
def test_remove_from_list_should_set_position_to_nil
|
|
135
|
-
assert_equal [1, 2, 3, 4], ArrayScopeListMixin.
|
|
135
|
+
assert_equal [1, 2, 3, 4], ArrayScopeListMixin.where(parent_id: 5, parent_type: 'ParentClass').order('pos').map(&:id)
|
|
136
136
|
|
|
137
|
-
ArrayScopeListMixin.
|
|
137
|
+
ArrayScopeListMixin.where(id: 2).first.remove_from_list
|
|
138
138
|
|
|
139
|
-
assert_equal [2, 1, 3, 4], ArrayScopeListMixin.
|
|
139
|
+
assert_equal [2, 1, 3, 4], ArrayScopeListMixin.where(parent_id: 5, parent_type: 'ParentClass').order('pos').map(&:id)
|
|
140
140
|
|
|
141
|
-
assert_equal 1, ArrayScopeListMixin.
|
|
142
|
-
assert_equal nil, ArrayScopeListMixin.
|
|
143
|
-
assert_equal 2, ArrayScopeListMixin.
|
|
144
|
-
assert_equal 3, ArrayScopeListMixin.
|
|
141
|
+
assert_equal 1, ArrayScopeListMixin.where(id: 1).first.pos
|
|
142
|
+
assert_equal nil, ArrayScopeListMixin.where(id: 2).first.pos
|
|
143
|
+
assert_equal 2, ArrayScopeListMixin.where(id: 3).first.pos
|
|
144
|
+
assert_equal 3, ArrayScopeListMixin.where(id: 4).first.pos
|
|
145
145
|
end
|
|
146
146
|
|
|
147
147
|
def test_remove_before_destroy_does_not_shift_lower_items_twice
|
|
148
|
-
assert_equal [1, 2, 3, 4], ArrayScopeListMixin.
|
|
148
|
+
assert_equal [1, 2, 3, 4], ArrayScopeListMixin.where(parent_id: 5, parent_type: 'ParentClass').order('pos').map(&:id)
|
|
149
149
|
|
|
150
|
-
ArrayScopeListMixin.
|
|
151
|
-
ArrayScopeListMixin.
|
|
150
|
+
ArrayScopeListMixin.where(id: 2).first.remove_from_list
|
|
151
|
+
ArrayScopeListMixin.where(id: 2).first.destroy
|
|
152
152
|
|
|
153
|
-
assert_equal [1, 3, 4], ArrayScopeListMixin.
|
|
153
|
+
assert_equal [1, 3, 4], ArrayScopeListMixin.where(parent_id: 5, parent_type: 'ParentClass').order('pos').map(&:id)
|
|
154
154
|
|
|
155
|
-
assert_equal 1, ArrayScopeListMixin.
|
|
156
|
-
assert_equal 2, ArrayScopeListMixin.
|
|
157
|
-
assert_equal 3, ArrayScopeListMixin.
|
|
155
|
+
assert_equal 1, ArrayScopeListMixin.where(id: 1).first.pos
|
|
156
|
+
assert_equal 2, ArrayScopeListMixin.where(id: 3).first.pos
|
|
157
|
+
assert_equal 3, ArrayScopeListMixin.where(id: 4).first.pos
|
|
158
158
|
end
|
|
159
159
|
end
|
|
160
160
|
end
|