acts_as_list 0.7.4 → 0.7.7
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 +5 -13
- data/.travis.yml +15 -0
- data/Appraisals +13 -3
- data/CHANGELOG.md +77 -2
- data/Gemfile +2 -2
- data/README.md +2 -1
- data/gemfiles/rails_3_2.gemfile +2 -1
- data/gemfiles/rails_4_1.gemfile +2 -1
- data/gemfiles/rails_4_2.gemfile +2 -1
- data/gemfiles/rails_5_0.gemfile +24 -0
- data/lib/acts_as_list/active_record/acts/list.rb +94 -79
- data/lib/acts_as_list/version.rb +1 -1
- data/test/helper.rb +2 -2
- data/test/shared.rb +1 -0
- data/test/shared_list.rb +13 -1
- data/test/shared_no_addition.rb +11 -0
- data/test/shared_quoting.rb +21 -0
- data/test/test_joined_list.rb +64 -0
- data/test/test_list.rb +148 -3
- metadata +16 -11
checksums.yaml
CHANGED
|
@@ -1,15 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
|
|
5
|
-
data.tar.gz: !binary |-
|
|
6
|
-
OThlMWNiYjU3MGRmMGQzNjA5NzQ1MDk1MzdiYTg1MGFjODJlNDJmYQ==
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: d62dacdeb7972152a2ee04cee3cccb8ef26898d7
|
|
4
|
+
data.tar.gz: fe6b02bfa1c5ed33407d1852c7b988a1848c7cd4
|
|
7
5
|
SHA512:
|
|
8
|
-
metadata.gz:
|
|
9
|
-
|
|
10
|
-
NmY4Y2FjY2U4YjczNjliZjFmYzYwYmMzYTNlNTA2MjU4NmVlODFmMzg1NGY0
|
|
11
|
-
OWNkN2Y4MGU2ZTM4YjM2YjY0MTZkNjcwMjk0NmQ1YzBkMmNjYjE=
|
|
12
|
-
data.tar.gz: !binary |-
|
|
13
|
-
Mzg4NGQwNmY2NjdjN2MxZWIzYWE4MWNiOTlkMTc5NGM5NTRiMzRmY2MwNDVh
|
|
14
|
-
ODI2YTVhZmUwMzE1OTAwNzA1OWZjMjc3ZGNhZmI1Y2ZmNmU4NmYzNGQ3ZTc1
|
|
15
|
-
OGUyZDE0NjZkZTVjNmQxZTJhOWUyNjdhOWIwMjJiMTg2YzA2NWI=
|
|
6
|
+
metadata.gz: 6b376b14646463802f4aee7080663eefdb3d7b1a43088df7126f57c84ecfb0a8730470efe4b57758f2b2079d6bd52b19f2a80293b211095318425d5892194897
|
|
7
|
+
data.tar.gz: fa104b99749d08767074e96f5fea1e97590ee841673660c39d03bb3d2cd50a3d2db2de4d1d195d5503d1bfadec7cbe84e046714f0ab98d0d509bc4c4797949e2
|
data/.travis.yml
CHANGED
|
@@ -9,9 +9,24 @@ rvm:
|
|
|
9
9
|
- 1.9.3
|
|
10
10
|
- 2.0.0
|
|
11
11
|
- 2.1.0
|
|
12
|
+
- 2.2.2
|
|
12
13
|
- jruby-19mode
|
|
13
14
|
- rbx-2
|
|
14
15
|
gemfile:
|
|
15
16
|
- gemfiles/rails_3_2.gemfile
|
|
16
17
|
- gemfiles/rails_4_1.gemfile
|
|
17
18
|
- gemfiles/rails_4_2.gemfile
|
|
19
|
+
- gemfiles/rails_5_0.gemfile
|
|
20
|
+
matrix:
|
|
21
|
+
exclude:
|
|
22
|
+
- rvm: 1.9.3
|
|
23
|
+
gemfile: gemfiles/rails_5_0.gemfile
|
|
24
|
+
- rvm: 2.0.0
|
|
25
|
+
gemfile: gemfiles/rails_5_0.gemfile
|
|
26
|
+
- rvm: 2.1.0
|
|
27
|
+
gemfile: gemfiles/rails_5_0.gemfile
|
|
28
|
+
- rvm: jruby-19mode
|
|
29
|
+
gemfile: gemfiles/rails_5_0.gemfile
|
|
30
|
+
- rvm: rbx-2
|
|
31
|
+
gemfile: gemfiles/rails_5_0.gemfile
|
|
32
|
+
|
data/Appraisals
CHANGED
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
appraise "rails-3-2" do
|
|
2
|
-
gem "activerecord", "~> 3.2.
|
|
2
|
+
gem "activerecord", "~> 3.2.22.2"
|
|
3
|
+
group :test do
|
|
4
|
+
gem "after_commit_exception_notification"
|
|
5
|
+
end
|
|
3
6
|
end
|
|
4
7
|
|
|
5
8
|
appraise "rails-4-1" do
|
|
6
|
-
gem "activerecord", "~> 4.1.
|
|
9
|
+
gem "activerecord", "~> 4.1.16"
|
|
10
|
+
group :test do
|
|
11
|
+
gem "after_commit_exception_notification"
|
|
12
|
+
end
|
|
7
13
|
end
|
|
8
14
|
|
|
9
15
|
appraise "rails-4-2" do
|
|
10
|
-
gem "activerecord", "~> 4.2.
|
|
16
|
+
gem "activerecord", "~> 4.2.7"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
appraise "rails-5-0" do
|
|
20
|
+
gem "activerecord", "~> 5.0.0"
|
|
11
21
|
end
|
data/CHANGELOG.md
CHANGED
|
@@ -1,7 +1,82 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
+
## [v0.7.6](https://github.com/swanandp/acts_as_list/tree/v0.7.6) (2016-07-15)
|
|
4
|
+
[Full Changelog](https://github.com/swanandp/acts_as_list/compare/v0.7.5...v0.7.6)
|
|
5
|
+
|
|
6
|
+
**Closed issues:**
|
|
7
|
+
|
|
8
|
+
- add\_new\_at nil with scope causes NoMethodError [\#211](https://github.com/swanandp/acts_as_list/issues/211)
|
|
9
|
+
|
|
10
|
+
**Merged pull requests:**
|
|
11
|
+
|
|
12
|
+
- Add class method acts\_as\_list\_top as reader for configured top\_of\_list [\#213](https://github.com/swanandp/acts_as_list/pull/213) ([krzysiek1507](https://github.com/krzysiek1507))
|
|
13
|
+
- Bugfix/add new at nil on scope change [\#212](https://github.com/swanandp/acts_as_list/pull/212) ([greatghoul](https://github.com/greatghoul))
|
|
14
|
+
|
|
15
|
+
## [v0.7.5](https://github.com/swanandp/acts_as_list/tree/v0.7.5) (2016-06-30)
|
|
16
|
+
[Full Changelog](https://github.com/swanandp/acts_as_list/compare/v0.7.4...v0.7.5)
|
|
17
|
+
|
|
18
|
+
**Implemented enhancements:**
|
|
19
|
+
|
|
20
|
+
- Touch when reordering [\#173](https://github.com/swanandp/acts_as_list/pull/173) ([botandrose](https://github.com/botandrose))
|
|
21
|
+
|
|
22
|
+
**Closed issues:**
|
|
23
|
+
|
|
24
|
+
- Exception raised when calling destroy "NameError - instance variable @scope\_changed not defined:" [\#206](https://github.com/swanandp/acts_as_list/issues/206)
|
|
25
|
+
- Undefined instance variable @scope\_changed since 0.7.3 [\#199](https://github.com/swanandp/acts_as_list/issues/199)
|
|
26
|
+
- Reordering large lists is slow [\#198](https://github.com/swanandp/acts_as_list/issues/198)
|
|
27
|
+
- Reparenting child leaves gap in source list in rails 5 [\#194](https://github.com/swanandp/acts_as_list/issues/194)
|
|
28
|
+
- Support rails 5 ? [\#186](https://github.com/swanandp/acts_as_list/issues/186)
|
|
29
|
+
- I get a NoMethodError: undefined method `acts\_as\_list' when trying to include acts\_as\_list [\#176](https://github.com/swanandp/acts_as_list/issues/176)
|
|
30
|
+
- Phenomenon of mysterious value of the position is skipped by one [\#166](https://github.com/swanandp/acts_as_list/issues/166)
|
|
31
|
+
- Model.find being called twice with acts\_as\_list on destroy [\#161](https://github.com/swanandp/acts_as_list/issues/161)
|
|
32
|
+
- `scope\_changed?` problem with acts\_as\_paranoid [\#158](https://github.com/swanandp/acts_as_list/issues/158)
|
|
33
|
+
- Inconsistent behaviour between Symbol and Array scopes [\#155](https://github.com/swanandp/acts_as_list/issues/155)
|
|
34
|
+
- insert\_at doesn't seem to be working in ActiveRecord callback \(Rails 4.2\) [\#150](https://github.com/swanandp/acts_as_list/issues/150)
|
|
35
|
+
- Project Documentation link redirects to expired domain [\#149](https://github.com/swanandp/acts_as_list/issues/149)
|
|
36
|
+
- Problem when updating an position of array of AR objects. [\#137](https://github.com/swanandp/acts_as_list/issues/137)
|
|
37
|
+
- Unexpected behaviour when inserting consecutive items with default positions [\#124](https://github.com/swanandp/acts_as_list/issues/124)
|
|
38
|
+
- self.reload prone to error [\#122](https://github.com/swanandp/acts_as_list/issues/122)
|
|
39
|
+
- Rails 3.0.x in\_list causes the return of default\_scope [\#120](https://github.com/swanandp/acts_as_list/issues/120)
|
|
40
|
+
- Relationships with dependency:destroy cause ActiveRecord::RecordNotFound [\#118](https://github.com/swanandp/acts_as_list/issues/118)
|
|
41
|
+
- Using insert\_at with values with type String [\#117](https://github.com/swanandp/acts_as_list/issues/117)
|
|
42
|
+
- Batch setting of position [\#112](https://github.com/swanandp/acts_as_list/issues/112)
|
|
43
|
+
- position: 0 now makes model pushed to top? [\#110](https://github.com/swanandp/acts_as_list/issues/110)
|
|
44
|
+
- Create element in default position [\#103](https://github.com/swanandp/acts_as_list/issues/103)
|
|
45
|
+
- Enhancement: Expose scope object [\#97](https://github.com/swanandp/acts_as_list/issues/97)
|
|
46
|
+
- Shuffle list [\#96](https://github.com/swanandp/acts_as_list/issues/96)
|
|
47
|
+
- Creating an item with a nil scope should not add it to the list [\#92](https://github.com/swanandp/acts_as_list/issues/92)
|
|
48
|
+
- Performance Improvements [\#88](https://github.com/swanandp/acts_as_list/issues/88)
|
|
49
|
+
- has\_many :through or has\_many\_and\_belongs\_to\_many support [\#86](https://github.com/swanandp/acts_as_list/issues/86)
|
|
50
|
+
- ActiveRecord dependency causes rake assets:compile to fail without access to a database [\#84](https://github.com/swanandp/acts_as_list/issues/84)
|
|
51
|
+
- move\_higher/move\_lower vs move\_to\_top/move\_to\_bottom act differently when item is already at top or bottom [\#77](https://github.com/swanandp/acts_as_list/issues/77)
|
|
52
|
+
- Limiting the list size [\#61](https://github.com/swanandp/acts_as_list/issues/61)
|
|
53
|
+
- Adding multiple creates strange ordering [\#55](https://github.com/swanandp/acts_as_list/issues/55)
|
|
54
|
+
- Feature: sort [\#26](https://github.com/swanandp/acts_as_list/issues/26)
|
|
55
|
+
|
|
56
|
+
**Merged pull requests:**
|
|
57
|
+
|
|
58
|
+
- Removed duplicated assignment [\#207](https://github.com/swanandp/acts_as_list/pull/207) ([shunwen](https://github.com/shunwen))
|
|
59
|
+
- Quote all identifiers [\#205](https://github.com/swanandp/acts_as_list/pull/205) ([fabn](https://github.com/fabn))
|
|
60
|
+
- Start testing Rails 5 [\#203](https://github.com/swanandp/acts_as_list/pull/203) ([brendon](https://github.com/brendon))
|
|
61
|
+
- Lock! the record before destroying [\#201](https://github.com/swanandp/acts_as_list/pull/201) ([brendon](https://github.com/brendon))
|
|
62
|
+
- Fix ambiguous column error when joining some relations [\#180](https://github.com/swanandp/acts_as_list/pull/180) ([natw](https://github.com/natw))
|
|
63
|
+
|
|
64
|
+
## [v0.7.4](https://github.com/swanandp/acts_as_list/tree/v0.7.4) (2016-04-15)
|
|
65
|
+
[Full Changelog](https://github.com/swanandp/acts_as_list/compare/v0.7.3...v0.7.4)
|
|
66
|
+
|
|
67
|
+
**Closed issues:**
|
|
68
|
+
|
|
69
|
+
- Releasing a new gem version [\#196](https://github.com/swanandp/acts_as_list/issues/196)
|
|
70
|
+
|
|
71
|
+
**Merged pull requests:**
|
|
72
|
+
|
|
73
|
+
- Fix scope changed [\#200](https://github.com/swanandp/acts_as_list/pull/200) ([brendon](https://github.com/brendon))
|
|
74
|
+
|
|
3
75
|
## [v0.7.3](https://github.com/swanandp/acts_as_list/tree/v0.7.3) (2016-04-14)
|
|
4
|
-
[Full Changelog](https://github.com/swanandp/acts_as_list/compare/
|
|
76
|
+
[Full Changelog](https://github.com/swanandp/acts_as_list/compare/v0.7.2...v0.7.3)
|
|
77
|
+
|
|
78
|
+
## [v0.7.2](https://github.com/swanandp/acts_as_list/tree/v0.7.2) (2016-04-01)
|
|
79
|
+
[Full Changelog](https://github.com/swanandp/acts_as_list/compare/0.7.2...v0.7.2)
|
|
5
80
|
|
|
6
81
|
**Closed issues:**
|
|
7
82
|
|
|
@@ -238,4 +313,4 @@
|
|
|
238
313
|
|
|
239
314
|
|
|
240
315
|
|
|
241
|
-
\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*
|
|
316
|
+
\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*
|
data/Gemfile
CHANGED
|
@@ -9,12 +9,12 @@ platforms :rbx do
|
|
|
9
9
|
gem "rubysl-test-unit"
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
gem "rack", "~> 1", platforms: [:ruby_19, :ruby_20, :ruby_21, :jruby]
|
|
13
|
+
|
|
13
14
|
gemspec
|
|
14
15
|
|
|
15
16
|
gem "rake"
|
|
16
17
|
gem "appraisal"
|
|
17
|
-
# Used to automatically generate changelog file
|
|
18
18
|
gem "github_changelog_generator", "1.9.0"
|
|
19
19
|
|
|
20
20
|
group :test do
|
data/README.md
CHANGED
|
@@ -95,6 +95,8 @@ default: '1'. Use this option to define the top of the list. Use 0 to make the c
|
|
|
95
95
|
default: ':bottom'. Use this option to specify whether objects get added to the :top or :bottom of the list. `nil` will result in new items not being added to the list on create, i.e, position will be kept nil after create.
|
|
96
96
|
|
|
97
97
|
## Versions
|
|
98
|
+
As of version `0.7.5` Rails 5 is supported.
|
|
99
|
+
|
|
98
100
|
All versions `0.1.5` onwards require Rails 3.0.x and higher.
|
|
99
101
|
|
|
100
102
|
## Build Status
|
|
@@ -106,7 +108,6 @@ All versions `0.1.5` onwards require Rails 3.0.x and higher.
|
|
|
106
108
|
## Roadmap
|
|
107
109
|
|
|
108
110
|
1. Sort based feature
|
|
109
|
-
2. Rails 4 compatibility and bye bye Rails 2! Older versions would of course continue to work with Rails 2, but there won't be any support on those.
|
|
110
111
|
|
|
111
112
|
## Contributing to `acts_as_list`
|
|
112
113
|
|
data/gemfiles/rails_3_2.gemfile
CHANGED
|
@@ -4,10 +4,11 @@ source "http://rubygems.org"
|
|
|
4
4
|
|
|
5
5
|
gem "sqlite3", :platforms => [:ruby]
|
|
6
6
|
gem "activerecord-jdbcsqlite3-adapter", :platforms => [:jruby]
|
|
7
|
+
gem "rack", "~> 1", :platforms => [:ruby_19, :ruby_20, :ruby_21, :jruby]
|
|
7
8
|
gem "rake"
|
|
8
9
|
gem "appraisal"
|
|
9
10
|
gem "github_changelog_generator", "1.9.0"
|
|
10
|
-
gem "activerecord", "~> 3.2.
|
|
11
|
+
gem "activerecord", "~> 3.2.22.2"
|
|
11
12
|
|
|
12
13
|
group :test do
|
|
13
14
|
gem "minitest", "~> 5.0"
|
data/gemfiles/rails_4_1.gemfile
CHANGED
|
@@ -4,10 +4,11 @@ source "http://rubygems.org"
|
|
|
4
4
|
|
|
5
5
|
gem "sqlite3", :platforms => [:ruby]
|
|
6
6
|
gem "activerecord-jdbcsqlite3-adapter", :platforms => [:jruby]
|
|
7
|
+
gem "rack", "~> 1", :platforms => [:ruby_19, :ruby_20, :ruby_21, :jruby]
|
|
7
8
|
gem "rake"
|
|
8
9
|
gem "appraisal"
|
|
9
10
|
gem "github_changelog_generator", "1.9.0"
|
|
10
|
-
gem "activerecord", "~> 4.1.
|
|
11
|
+
gem "activerecord", "~> 4.1.16"
|
|
11
12
|
|
|
12
13
|
group :test do
|
|
13
14
|
gem "minitest", "~> 5.0"
|
data/gemfiles/rails_4_2.gemfile
CHANGED
|
@@ -4,10 +4,11 @@ source "http://rubygems.org"
|
|
|
4
4
|
|
|
5
5
|
gem "sqlite3", :platforms => [:ruby]
|
|
6
6
|
gem "activerecord-jdbcsqlite3-adapter", :platforms => [:jruby]
|
|
7
|
+
gem "rack", "~> 1", :platforms => [:ruby_19, :ruby_20, :ruby_21, :jruby]
|
|
7
8
|
gem "rake"
|
|
8
9
|
gem "appraisal"
|
|
9
10
|
gem "github_changelog_generator", "1.9.0"
|
|
10
|
-
gem "activerecord", "~> 4.2.
|
|
11
|
+
gem "activerecord", "~> 4.2.7"
|
|
11
12
|
|
|
12
13
|
group :test do
|
|
13
14
|
gem "minitest", "~> 5.0"
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# This file was generated by Appraisal
|
|
2
|
+
|
|
3
|
+
source "http://rubygems.org"
|
|
4
|
+
|
|
5
|
+
gem "sqlite3", :platforms => [:ruby]
|
|
6
|
+
gem "activerecord-jdbcsqlite3-adapter", :platforms => [:jruby]
|
|
7
|
+
gem "rack", "~> 1", :platforms => [:ruby_19, :ruby_20, :ruby_21, :jruby]
|
|
8
|
+
gem "rake"
|
|
9
|
+
gem "appraisal"
|
|
10
|
+
gem "github_changelog_generator", "1.9.0"
|
|
11
|
+
gem "activerecord", "~> 5.0.0"
|
|
12
|
+
|
|
13
|
+
group :test do
|
|
14
|
+
gem "minitest", "~> 5.0"
|
|
15
|
+
gem "test_after_commit", "~> 0.4.2"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
platforms :rbx do
|
|
19
|
+
gem "rubysl", "~> 2.0"
|
|
20
|
+
gem "rubinius-developer_tools"
|
|
21
|
+
gem "rubysl-test-unit"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
gemspec :path => "../"
|
|
@@ -74,8 +74,13 @@ module ActiveRecord
|
|
|
74
74
|
)
|
|
75
75
|
end
|
|
76
76
|
|
|
77
|
+
quoted_position_column = connection.quote_column_name(configuration[:column])
|
|
78
|
+
quoted_position_column_with_table_name = "#{quoted_table_name}.#{quoted_position_column}"
|
|
79
|
+
|
|
77
80
|
class_eval <<-EOV, __FILE__, __LINE__ + 1
|
|
78
|
-
|
|
81
|
+
def self.acts_as_list_top
|
|
82
|
+
#{configuration[:top_of_list]}.to_i
|
|
83
|
+
end
|
|
79
84
|
|
|
80
85
|
def acts_as_list_top
|
|
81
86
|
#{configuration[:top_of_list]}.to_i
|
|
@@ -111,23 +116,46 @@ module ActiveRecord
|
|
|
111
116
|
attr_accessible :#{configuration[:column]}
|
|
112
117
|
end
|
|
113
118
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
before_destroy :reload_position
|
|
117
|
-
after_destroy :decrement_positions_on_lower_items
|
|
118
|
-
|
|
119
|
-
before_update :check_scope
|
|
120
|
-
after_update :update_positions
|
|
119
|
+
scope :in_list, lambda { where(%q{#{quoted_position_column_with_table_name} IS NOT NULL}) }
|
|
121
120
|
|
|
122
|
-
|
|
121
|
+
def self.decrement_all
|
|
122
|
+
update_all_with_touch %q(#{quoted_position_column} = (#{quoted_position_column_with_table_name} - 1))
|
|
123
|
+
end
|
|
123
124
|
|
|
124
|
-
|
|
125
|
+
def self.increment_all
|
|
126
|
+
update_all_with_touch %q(#{quoted_position_column} = (#{quoted_position_column_with_table_name} + 1))
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def self.update_all_with_touch(updates)
|
|
130
|
+
record = new
|
|
131
|
+
attrs = record.send(:timestamp_attributes_for_update_in_model)
|
|
132
|
+
now = record.send(:current_time_from_proper_timezone)
|
|
133
|
+
|
|
134
|
+
query = attrs.map { |attr| %(\#{connection.quote_column_name(attr)} = :now) }
|
|
135
|
+
query.push updates
|
|
136
|
+
query = query.join(", ")
|
|
137
|
+
|
|
138
|
+
update_all([query, now: now])
|
|
139
|
+
end
|
|
125
140
|
EOV
|
|
126
141
|
|
|
142
|
+
attr_reader :position_changed
|
|
143
|
+
|
|
144
|
+
before_validation :check_top_position
|
|
145
|
+
|
|
146
|
+
before_destroy :lock!
|
|
147
|
+
after_destroy :decrement_positions_on_lower_items
|
|
148
|
+
|
|
149
|
+
before_update :check_scope
|
|
150
|
+
after_update :update_positions
|
|
151
|
+
|
|
152
|
+
after_commit :clear_scope_changed
|
|
153
|
+
|
|
127
154
|
if configuration[:add_new_at].present?
|
|
128
|
-
|
|
155
|
+
before_create "add_to_list_#{configuration[:add_new_at]}".to_sym
|
|
129
156
|
end
|
|
130
157
|
|
|
158
|
+
include ::ActiveRecord::Acts::List::InstanceMethods
|
|
131
159
|
end
|
|
132
160
|
end
|
|
133
161
|
|
|
@@ -232,10 +260,10 @@ module ActiveRecord
|
|
|
232
260
|
limit ||= acts_as_list_list.count
|
|
233
261
|
position_value = send(position_column)
|
|
234
262
|
acts_as_list_list.
|
|
235
|
-
where("#{
|
|
236
|
-
where("#{
|
|
263
|
+
where("#{quoted_position_column_with_table_name} < ?", position_value).
|
|
264
|
+
where("#{quoted_position_column_with_table_name} >= ?", position_value - limit).
|
|
237
265
|
limit(limit).
|
|
238
|
-
order("#{
|
|
266
|
+
order("#{quoted_position_column_with_table_name} ASC")
|
|
239
267
|
end
|
|
240
268
|
|
|
241
269
|
# Return the next lower item in the list.
|
|
@@ -250,10 +278,10 @@ module ActiveRecord
|
|
|
250
278
|
limit ||= acts_as_list_list.count
|
|
251
279
|
position_value = send(position_column)
|
|
252
280
|
acts_as_list_list.
|
|
253
|
-
where("#{
|
|
254
|
-
where("#{
|
|
281
|
+
where("#{quoted_position_column_with_table_name} > ?", position_value).
|
|
282
|
+
where("#{quoted_position_column_with_table_name} <= ?", position_value + limit).
|
|
255
283
|
limit(limit).
|
|
256
|
-
order("#{
|
|
284
|
+
order("#{quoted_position_column_with_table_name} ASC")
|
|
257
285
|
end
|
|
258
286
|
|
|
259
287
|
# Test if this record is in a list
|
|
@@ -298,7 +326,7 @@ module ActiveRecord
|
|
|
298
326
|
# A poorly named method. It will insert the item at the desired position if the position
|
|
299
327
|
# has been set manually using position=, not necessarily the bottom of the list
|
|
300
328
|
def add_to_list_bottom
|
|
301
|
-
if not_in_list? || internal_scope_changed? &&
|
|
329
|
+
if not_in_list? || internal_scope_changed? && !position_changed || default_position?
|
|
302
330
|
self[position_column] = bottom_position_in_list.to_i + 1
|
|
303
331
|
else
|
|
304
332
|
increment_positions_on_lower_items(self[position_column], id)
|
|
@@ -323,12 +351,11 @@ module ActiveRecord
|
|
|
323
351
|
|
|
324
352
|
# Returns the bottom item
|
|
325
353
|
def bottom_item(except = nil)
|
|
326
|
-
conditions =
|
|
327
|
-
conditions = except ? "#{self.class.primary_key} != #{self.class.connection.quote(except.id)}" : {}
|
|
354
|
+
conditions = except ? "#{quoted_table_name}.#{self.class.primary_key} != #{self.class.connection.quote(except.id)}" : {}
|
|
328
355
|
acts_as_list_list.in_list.where(
|
|
329
356
|
conditions
|
|
330
357
|
).order(
|
|
331
|
-
"#{
|
|
358
|
+
"#{quoted_position_column_with_table_name} DESC"
|
|
332
359
|
).first
|
|
333
360
|
end
|
|
334
361
|
|
|
@@ -344,56 +371,38 @@ module ActiveRecord
|
|
|
344
371
|
|
|
345
372
|
# This has the effect of moving all the higher items up one.
|
|
346
373
|
def decrement_positions_on_higher_items(position)
|
|
347
|
-
acts_as_list_list.where(
|
|
348
|
-
"#{position_column} <= #{position}"
|
|
349
|
-
).update_all(
|
|
350
|
-
"#{position_column} = (#{position_column} - 1)"
|
|
351
|
-
)
|
|
374
|
+
acts_as_list_list.where("#{quoted_position_column_with_table_name} <= ?", position).decrement_all
|
|
352
375
|
end
|
|
353
376
|
|
|
354
377
|
# This has the effect of moving all the lower items up one.
|
|
355
378
|
def decrement_positions_on_lower_items(position=nil)
|
|
356
379
|
return unless in_list?
|
|
357
380
|
position ||= send(position_column).to_i
|
|
358
|
-
acts_as_list_list.where(
|
|
359
|
-
"#{position_column} > #{position}"
|
|
360
|
-
).update_all(
|
|
361
|
-
"#{position_column} = (#{position_column} - 1)"
|
|
362
|
-
)
|
|
381
|
+
acts_as_list_list.where("#{quoted_position_column_with_table_name} > ?", position).decrement_all
|
|
363
382
|
end
|
|
364
383
|
|
|
365
384
|
# This has the effect of moving all the higher items down one.
|
|
366
385
|
def increment_positions_on_higher_items
|
|
367
386
|
return unless in_list?
|
|
368
|
-
acts_as_list_list.where(
|
|
369
|
-
"#{position_column} < #{send(position_column).to_i}"
|
|
370
|
-
).update_all(
|
|
371
|
-
"#{position_column} = (#{position_column} + 1)"
|
|
372
|
-
)
|
|
387
|
+
acts_as_list_list.where("#{quoted_position_column_with_table_name} < #{send(position_column).to_i}").increment_all
|
|
373
388
|
end
|
|
374
389
|
|
|
375
390
|
# This has the effect of moving all the lower items down one.
|
|
376
391
|
def increment_positions_on_lower_items(position, avoid_id = nil)
|
|
377
|
-
avoid_id_condition = avoid_id ? " AND #{self.class.primary_key} != #{self.class.connection.quote(avoid_id)}" : ''
|
|
392
|
+
avoid_id_condition = avoid_id ? " AND #{quoted_table_name}.#{self.class.primary_key} != #{self.class.connection.quote(avoid_id)}" : ''
|
|
378
393
|
|
|
379
|
-
acts_as_list_list.where(
|
|
380
|
-
"#{position_column} >= #{position}#{avoid_id_condition}"
|
|
381
|
-
).update_all(
|
|
382
|
-
"#{position_column} = (#{position_column} + 1)"
|
|
383
|
-
)
|
|
394
|
+
acts_as_list_list.where("#{quoted_position_column_with_table_name} >= #{position}#{avoid_id_condition}").increment_all
|
|
384
395
|
end
|
|
385
396
|
|
|
386
397
|
# Increments position (<tt>position_column</tt>) of all items in the list.
|
|
387
398
|
def increment_positions_on_all_items
|
|
388
|
-
acts_as_list_list.
|
|
389
|
-
"#{position_column} = (#{position_column} + 1)"
|
|
390
|
-
)
|
|
399
|
+
acts_as_list_list.increment_all
|
|
391
400
|
end
|
|
392
401
|
|
|
393
402
|
# Reorders intermediate items to support moving an item from old_position to new_position.
|
|
394
403
|
def shuffle_positions_on_intermediate_items(old_position, new_position, avoid_id = nil)
|
|
395
404
|
return if old_position == new_position
|
|
396
|
-
avoid_id_condition = avoid_id ? " AND #{self.class.primary_key} != #{self.class.connection.quote(avoid_id)}" : ''
|
|
405
|
+
avoid_id_condition = avoid_id ? " AND #{quoted_table_name}.#{self.class.primary_key} != #{self.class.connection.quote(avoid_id)}" : ''
|
|
397
406
|
|
|
398
407
|
if old_position < new_position
|
|
399
408
|
# Decrement position of intermediate items
|
|
@@ -401,37 +410,35 @@ module ActiveRecord
|
|
|
401
410
|
# e.g., if moving an item from 2 to 5,
|
|
402
411
|
# move [3, 4, 5] to [2, 3, 4]
|
|
403
412
|
acts_as_list_list.where(
|
|
404
|
-
"#{
|
|
413
|
+
"#{quoted_position_column_with_table_name} > ?", old_position
|
|
405
414
|
).where(
|
|
406
|
-
"#{
|
|
407
|
-
).
|
|
408
|
-
"#{position_column} = (#{position_column} - 1)"
|
|
409
|
-
)
|
|
415
|
+
"#{quoted_position_column_with_table_name} <= #{new_position}#{avoid_id_condition}"
|
|
416
|
+
).decrement_all
|
|
410
417
|
else
|
|
411
418
|
# Increment position of intermediate items
|
|
412
419
|
#
|
|
413
420
|
# e.g., if moving an item from 5 to 2,
|
|
414
421
|
# move [2, 3, 4] to [3, 4, 5]
|
|
415
422
|
acts_as_list_list.where(
|
|
416
|
-
"#{
|
|
423
|
+
"#{quoted_position_column_with_table_name} >= ?", new_position
|
|
417
424
|
).where(
|
|
418
|
-
"#{
|
|
419
|
-
).
|
|
420
|
-
"#{position_column} = (#{position_column} + 1)"
|
|
421
|
-
)
|
|
425
|
+
"#{quoted_position_column_with_table_name} < #{old_position}#{avoid_id_condition}"
|
|
426
|
+
).increment_all
|
|
422
427
|
end
|
|
423
428
|
end
|
|
424
429
|
|
|
425
430
|
def insert_at_position(position)
|
|
426
431
|
return set_list_position(position) if new_record?
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
432
|
+
with_lock do
|
|
433
|
+
if in_list?
|
|
434
|
+
old_position = send(position_column).to_i
|
|
435
|
+
return if position == old_position
|
|
436
|
+
shuffle_positions_on_intermediate_items(old_position, position)
|
|
437
|
+
else
|
|
438
|
+
increment_positions_on_lower_items(position)
|
|
439
|
+
end
|
|
440
|
+
set_list_position(position)
|
|
433
441
|
end
|
|
434
|
-
set_list_position(position)
|
|
435
442
|
end
|
|
436
443
|
|
|
437
444
|
# used by insert_at_position instead of remove_from_list, as postgresql raises error if position_column has non-null constraint
|
|
@@ -448,37 +455,31 @@ module ActiveRecord
|
|
|
448
455
|
new_position = send(position_column).to_i
|
|
449
456
|
|
|
450
457
|
return unless acts_as_list_list.where(
|
|
451
|
-
"#{
|
|
458
|
+
"#{quoted_position_column_with_table_name} = #{new_position}"
|
|
452
459
|
).count > 1
|
|
453
460
|
shuffle_positions_on_intermediate_items old_position, new_position, id
|
|
454
461
|
end
|
|
455
462
|
|
|
456
463
|
def internal_scope_changed?
|
|
457
464
|
return @scope_changed if defined?(@scope_changed)
|
|
458
|
-
|
|
465
|
+
|
|
459
466
|
@scope_changed = scope_changed?
|
|
460
467
|
end
|
|
461
468
|
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
@changed_attributes.each do |k, _|
|
|
465
|
-
if self.class.column_names.include? k
|
|
466
|
-
@changed_attributes[k], self[k] = self[k], @changed_attributes[k]
|
|
467
|
-
end
|
|
468
|
-
end
|
|
469
|
+
def clear_scope_changed
|
|
470
|
+
remove_instance_variable(:@scope_changed) if defined?(@scope_changed)
|
|
469
471
|
end
|
|
470
472
|
|
|
471
473
|
def check_scope
|
|
472
474
|
if internal_scope_changed?
|
|
473
|
-
|
|
475
|
+
cached_changes = changes
|
|
476
|
+
|
|
477
|
+
cached_changes.each { |attribute, values| self[attribute] = values[0] }
|
|
474
478
|
send('decrement_positions_on_lower_items') if lower_item
|
|
475
|
-
|
|
476
|
-
send("add_to_list_#{add_new_at}")
|
|
477
|
-
end
|
|
478
|
-
end
|
|
479
|
+
cached_changes.each { |attribute, values| self[attribute] = values[1] }
|
|
479
480
|
|
|
480
|
-
|
|
481
|
-
|
|
481
|
+
send("add_to_list_#{add_new_at}") if add_new_at.present?
|
|
482
|
+
end
|
|
482
483
|
end
|
|
483
484
|
|
|
484
485
|
# This check is skipped if the position is currently the default position from the table
|
|
@@ -488,6 +489,20 @@ module ActiveRecord
|
|
|
488
489
|
self[position_column] = acts_as_list_top
|
|
489
490
|
end
|
|
490
491
|
end
|
|
492
|
+
|
|
493
|
+
# When using raw column name it must be quoted otherwise it can raise syntax errors with SQL keywords (e.g. order)
|
|
494
|
+
def quoted_position_column
|
|
495
|
+
@_quoted_position_column ||= self.class.connection.quote_column_name(position_column)
|
|
496
|
+
end
|
|
497
|
+
|
|
498
|
+
# Used in order clauses
|
|
499
|
+
def quoted_table_name
|
|
500
|
+
@_quoted_table_name ||= acts_as_list_class.quoted_table_name
|
|
501
|
+
end
|
|
502
|
+
|
|
503
|
+
def quoted_position_column_with_table_name
|
|
504
|
+
@_quoted_position_column_with_table_name ||= "#{quoted_table_name}.#{quoted_position_column}"
|
|
505
|
+
end
|
|
491
506
|
end
|
|
492
507
|
end
|
|
493
508
|
end
|
data/lib/acts_as_list/version.rb
CHANGED
data/test/helper.rb
CHANGED
|
@@ -12,9 +12,9 @@ require "minitest/autorun"
|
|
|
12
12
|
require "#{File.dirname(__FILE__)}/../init"
|
|
13
13
|
|
|
14
14
|
if defined?(ActiveRecord::VERSION) &&
|
|
15
|
-
ActiveRecord::VERSION::MAJOR
|
|
16
|
-
(ActiveRecord::VERSION::MAJOR == 4 && ActiveRecord::VERSION::MINOR >= 2)
|
|
15
|
+
ActiveRecord::VERSION::MAJOR == 4 && ActiveRecord::VERSION::MINOR >= 2
|
|
17
16
|
|
|
17
|
+
# Was removed in Rails 5 and is effectively true.
|
|
18
18
|
ActiveRecord::Base.raise_in_transactional_callbacks = true
|
|
19
19
|
end
|
|
20
20
|
|
data/test/shared.rb
CHANGED
data/test/shared_list.rb
CHANGED
|
@@ -104,6 +104,12 @@ module Shared
|
|
|
104
104
|
|
|
105
105
|
new4.reload
|
|
106
106
|
assert_equal 5, new4.pos
|
|
107
|
+
|
|
108
|
+
last1 = ListMixin.order('pos').last
|
|
109
|
+
last2 = ListMixin.order('pos').last
|
|
110
|
+
last1.insert_at(1)
|
|
111
|
+
last2.insert_at(1)
|
|
112
|
+
assert_equal [1, 2, 3, 4, 5], ListMixin.where(parent_id: 20).order('pos').map(&:pos)
|
|
107
113
|
end
|
|
108
114
|
|
|
109
115
|
def test_delete_middle
|
|
@@ -142,7 +148,7 @@ module Shared
|
|
|
142
148
|
|
|
143
149
|
def test_update_position_when_scope_changes
|
|
144
150
|
assert_equal [1, 2, 3, 4], ListMixin.where(parent_id: 5).order('pos').map(&:id)
|
|
145
|
-
|
|
151
|
+
ListMixin.create(parent_id: 6)
|
|
146
152
|
|
|
147
153
|
ListMixin.where(id: 2).first.move_within_scope(6)
|
|
148
154
|
|
|
@@ -246,5 +252,11 @@ module Shared
|
|
|
246
252
|
|
|
247
253
|
assert_equal [5, 1, 6, 2, 3, 4], ListMixin.where(parent_id: 5).order('pos').map(&:id)
|
|
248
254
|
end
|
|
255
|
+
|
|
256
|
+
def test_non_persisted_records_dont_get_lock_called
|
|
257
|
+
new = ListMixin.new(parent_id: 5)
|
|
258
|
+
|
|
259
|
+
new.destroy
|
|
260
|
+
end
|
|
249
261
|
end
|
|
250
262
|
end
|
data/test/shared_no_addition.rb
CHANGED
|
@@ -21,5 +21,16 @@ module Shared
|
|
|
21
21
|
assert !new.in_list?
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
+
def test_update_scope_does_not_add_to_list
|
|
25
|
+
new = NoAdditionMixin.create
|
|
26
|
+
|
|
27
|
+
new.update_attribute(:parent_id, 20)
|
|
28
|
+
new.reload
|
|
29
|
+
assert !new.in_list?
|
|
30
|
+
|
|
31
|
+
new.update_attribute(:parent_id, 5)
|
|
32
|
+
new.reload
|
|
33
|
+
assert !new.in_list?
|
|
34
|
+
end
|
|
24
35
|
end
|
|
25
36
|
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module Shared
|
|
2
|
+
module Quoting
|
|
3
|
+
|
|
4
|
+
def setup
|
|
5
|
+
3.times { |counter| QuotedList.create! order: counter }
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def test_create
|
|
9
|
+
assert_equal QuotedList.in_list.size, 3
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# This test execute raw queries involving table name
|
|
13
|
+
def test_moving
|
|
14
|
+
item = QuotedList.first
|
|
15
|
+
item.higher_items
|
|
16
|
+
item.lower_items
|
|
17
|
+
item.send :bottom_item # Part of private api
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
require 'helper'
|
|
2
|
+
|
|
3
|
+
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
|
|
4
|
+
ActiveRecord::Schema.verbose = false
|
|
5
|
+
|
|
6
|
+
class Section < ActiveRecord::Base
|
|
7
|
+
has_many :items
|
|
8
|
+
acts_as_list
|
|
9
|
+
|
|
10
|
+
scope :visible, -> { where(visible: true) }
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
class Item < ActiveRecord::Base
|
|
14
|
+
belongs_to :section
|
|
15
|
+
acts_as_list scope: :section
|
|
16
|
+
|
|
17
|
+
scope :visible, -> { where(visible: true).joins(:section).merge(Section.visible) }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
class JoinedTestCase < Minitest::Test
|
|
21
|
+
def setup
|
|
22
|
+
ActiveRecord::Base.connection.create_table :sections do |t|
|
|
23
|
+
t.column :position, :integer
|
|
24
|
+
t.column :visible, :boolean, default: true
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
ActiveRecord::Base.connection.create_table :items do |t|
|
|
28
|
+
t.column :position, :integer
|
|
29
|
+
t.column :section_id, :integer
|
|
30
|
+
t.column :visible, :boolean, default: true
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
ActiveRecord::Base.connection.schema_cache.clear!
|
|
34
|
+
[Section, Item].each(&:reset_column_information)
|
|
35
|
+
super
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def teardown
|
|
39
|
+
ActiveRecord::Base.connection.tables.each do |table|
|
|
40
|
+
ActiveRecord::Base.connection.drop_table(table)
|
|
41
|
+
end
|
|
42
|
+
super
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# joining the relation returned by `#higher_items` or `#lower_items` to another table
|
|
47
|
+
# previously could result in ambiguous column names in the query
|
|
48
|
+
class TestHigherLowerItems < JoinedTestCase
|
|
49
|
+
def test_higher_items
|
|
50
|
+
section = Section.create
|
|
51
|
+
item1 = Item.create section: section
|
|
52
|
+
item2 = Item.create section: section
|
|
53
|
+
item3 = Item.create section: section
|
|
54
|
+
assert_equal item3.higher_items.visible, [item1, item2]
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def test_lower_items
|
|
58
|
+
section = Section.create
|
|
59
|
+
item1 = Item.create section: section
|
|
60
|
+
item2 = Item.create section: section
|
|
61
|
+
item3 = Item.create section: section
|
|
62
|
+
assert_equal item1.lower_items.visible, [item2, item3]
|
|
63
|
+
end
|
|
64
|
+
end
|
data/test/test_list.rb
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
# NOTE: following now done in helper.rb (better Readability)
|
|
2
2
|
require 'helper'
|
|
3
3
|
|
|
4
|
-
ActiveRecord::Base.establish_connection(
|
|
4
|
+
ActiveRecord::Base.establish_connection(
|
|
5
|
+
adapter: "sqlite3",
|
|
6
|
+
database: 'file:memdb1?mode=memory&cache=shared'
|
|
7
|
+
)
|
|
5
8
|
ActiveRecord::Schema.verbose = false
|
|
6
9
|
|
|
7
10
|
def setup_db(position_options = {})
|
|
@@ -16,9 +19,14 @@ def setup_db(position_options = {})
|
|
|
16
19
|
t.column :state, :integer
|
|
17
20
|
end
|
|
18
21
|
|
|
22
|
+
# This table is used to test table names and column names quoting
|
|
23
|
+
ActiveRecord::Base.connection.create_table 'table-name' do |t|
|
|
24
|
+
t.column :order, :integer
|
|
25
|
+
end
|
|
26
|
+
|
|
19
27
|
mixins = [ Mixin, ListMixin, ListMixinSub1, ListMixinSub2, ListWithStringScopeMixin,
|
|
20
28
|
ArrayScopeListMixin, ZeroBasedMixin, DefaultScopedMixin,
|
|
21
|
-
DefaultScopedWhereMixin, TopAdditionMixin, NoAdditionMixin ]
|
|
29
|
+
DefaultScopedWhereMixin, TopAdditionMixin, NoAdditionMixin, QuotedList ]
|
|
22
30
|
|
|
23
31
|
mixins << EnumArrayScopeListMixin if rails_4
|
|
24
32
|
|
|
@@ -42,7 +50,13 @@ def rails_4
|
|
|
42
50
|
end
|
|
43
51
|
|
|
44
52
|
def teardown_db
|
|
45
|
-
ActiveRecord::
|
|
53
|
+
if ActiveRecord::VERSION::MAJOR >= 5
|
|
54
|
+
tables = ActiveRecord::Base.connection.data_sources
|
|
55
|
+
else
|
|
56
|
+
tables = ActiveRecord::Base.connection.tables
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
tables.each do |table|
|
|
46
60
|
ActiveRecord::Base.connection.drop_table(table)
|
|
47
61
|
end
|
|
48
62
|
end
|
|
@@ -149,6 +163,18 @@ end
|
|
|
149
163
|
class TheBaseSubclass < TheBaseClass
|
|
150
164
|
end
|
|
151
165
|
|
|
166
|
+
class DBConfigTest < Minitest::Test
|
|
167
|
+
def test_db_config
|
|
168
|
+
# make sure sqlite3 accepts multi threaded access
|
|
169
|
+
assert_equal "file:memdb1?mode=memory&cache=shared", ActiveRecord::Base.connection.pool.spec.config[:database]
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
class QuotedList < ActiveRecord::Base
|
|
174
|
+
self.table_name = 'table-name'
|
|
175
|
+
acts_as_list column: :order
|
|
176
|
+
end
|
|
177
|
+
|
|
152
178
|
class ActsAsListTestCase < Minitest::Test
|
|
153
179
|
# No default test required as this class is abstract.
|
|
154
180
|
# Need for test/unit.
|
|
@@ -184,6 +210,37 @@ class ListTest < ActsAsListTestCase
|
|
|
184
210
|
setup_db
|
|
185
211
|
super
|
|
186
212
|
end
|
|
213
|
+
|
|
214
|
+
def test_insert_race_condition
|
|
215
|
+
# the bigger n is the more likely we will have a race condition
|
|
216
|
+
n = 1000
|
|
217
|
+
(1..n).each do |counter|
|
|
218
|
+
node = ListMixin.new parent_id: 1
|
|
219
|
+
node.pos = counter
|
|
220
|
+
node.save!
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
wait_for_it = true
|
|
224
|
+
threads = []
|
|
225
|
+
4.times do |i|
|
|
226
|
+
threads << Thread.new do
|
|
227
|
+
true while wait_for_it
|
|
228
|
+
ActiveRecord::Base.connection_pool.with_connection do |c|
|
|
229
|
+
n.times do
|
|
230
|
+
begin
|
|
231
|
+
ListMixin.where(parent_id: 1).order(:pos).last.insert_at(1)
|
|
232
|
+
rescue Exception
|
|
233
|
+
# ignore SQLite3::SQLException due to table locking
|
|
234
|
+
end
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
wait_for_it = false
|
|
240
|
+
threads.each(&:join)
|
|
241
|
+
|
|
242
|
+
assert_equal (1..n).to_a, ListMixin.where(parent_id: 1).order('pos').map(&:pos)
|
|
243
|
+
end
|
|
187
244
|
end
|
|
188
245
|
|
|
189
246
|
class ListWithCallbackTest < ActsAsListTestCase
|
|
@@ -243,6 +300,15 @@ class ArrayScopeListTestWithDefault < ActsAsListTestCase
|
|
|
243
300
|
end
|
|
244
301
|
end
|
|
245
302
|
|
|
303
|
+
class QuotingTestList < ActsAsListTestCase
|
|
304
|
+
include Shared::Quoting
|
|
305
|
+
|
|
306
|
+
def setup
|
|
307
|
+
setup_db_with_default
|
|
308
|
+
super
|
|
309
|
+
end
|
|
310
|
+
end
|
|
311
|
+
|
|
246
312
|
class DefaultScopedTest < ActsAsListTestCase
|
|
247
313
|
def setup
|
|
248
314
|
setup_db
|
|
@@ -603,3 +669,82 @@ class MultipleListsArrayScopeTest < ActsAsListTestCase
|
|
|
603
669
|
assert_equal [1], ArrayScopeListMixin.where(:parent_id => 4, :parent_type => 'anything').order(:pos).map(&:pos)
|
|
604
670
|
end
|
|
605
671
|
end
|
|
672
|
+
|
|
673
|
+
class TouchTest < ActsAsListTestCase
|
|
674
|
+
def setup
|
|
675
|
+
setup_db
|
|
676
|
+
4.times { ListMixin.create! updated_at: yesterday }
|
|
677
|
+
end
|
|
678
|
+
|
|
679
|
+
def now
|
|
680
|
+
Time.now.utc
|
|
681
|
+
end
|
|
682
|
+
|
|
683
|
+
def yesterday
|
|
684
|
+
1.day.ago
|
|
685
|
+
end
|
|
686
|
+
|
|
687
|
+
def updated_ats
|
|
688
|
+
ListMixin.pluck(:updated_at)
|
|
689
|
+
end
|
|
690
|
+
|
|
691
|
+
def test_moving_item_lower_touches_self_and_lower_item
|
|
692
|
+
ListMixin.first.move_lower
|
|
693
|
+
updated_ats[0..1].each do |updated_at|
|
|
694
|
+
assert_in_delta updated_at, now, 1.second
|
|
695
|
+
end
|
|
696
|
+
updated_ats[2..3].each do |updated_at|
|
|
697
|
+
assert_in_delta updated_at, yesterday, 1.second
|
|
698
|
+
end
|
|
699
|
+
end
|
|
700
|
+
|
|
701
|
+
def test_moving_item_higher_touches_self_and_higher_item
|
|
702
|
+
ListMixin.all.second.move_higher
|
|
703
|
+
updated_ats[0..1].each do |updated_at|
|
|
704
|
+
assert_in_delta updated_at, now, 1.second
|
|
705
|
+
end
|
|
706
|
+
updated_ats[2..3].each do |updated_at|
|
|
707
|
+
assert_in_delta updated_at, yesterday, 1.second
|
|
708
|
+
end
|
|
709
|
+
end
|
|
710
|
+
|
|
711
|
+
def test_moving_item_to_bottom_touches_all_other_items
|
|
712
|
+
ListMixin.first.move_to_bottom
|
|
713
|
+
updated_ats.each do |updated_at|
|
|
714
|
+
assert_in_delta updated_at, now, 1.second
|
|
715
|
+
end
|
|
716
|
+
end
|
|
717
|
+
|
|
718
|
+
def test_moving_item_to_top_touches_all_other_items
|
|
719
|
+
ListMixin.last.move_to_top
|
|
720
|
+
updated_ats.each do |updated_at|
|
|
721
|
+
assert_in_delta updated_at, now, 1.second
|
|
722
|
+
end
|
|
723
|
+
end
|
|
724
|
+
|
|
725
|
+
def test_removing_item_touches_all_lower_items
|
|
726
|
+
ListMixin.all.third.remove_from_list
|
|
727
|
+
updated_ats[0..1].each do |updated_at|
|
|
728
|
+
assert_in_delta updated_at, yesterday, 1.second
|
|
729
|
+
end
|
|
730
|
+
updated_ats[2..2].each do |updated_at|
|
|
731
|
+
assert_in_delta updated_at, now, 1.second
|
|
732
|
+
end
|
|
733
|
+
end
|
|
734
|
+
end
|
|
735
|
+
|
|
736
|
+
class ActsAsListTopTest < ActsAsListTestCase
|
|
737
|
+
def setup
|
|
738
|
+
setup_db
|
|
739
|
+
end
|
|
740
|
+
|
|
741
|
+
def test_acts_as_list_top
|
|
742
|
+
assert_equal 1, TheBaseSubclass.new.acts_as_list_top
|
|
743
|
+
assert_equal 0, ZeroBasedMixin.new.acts_as_list_top
|
|
744
|
+
end
|
|
745
|
+
|
|
746
|
+
def test_class_acts_as_list_top
|
|
747
|
+
assert_equal 1, TheBaseSubclass.acts_as_list_top
|
|
748
|
+
assert_equal 0, ZeroBasedMixin.acts_as_list_top
|
|
749
|
+
end
|
|
750
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: acts_as_list
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.7.
|
|
4
|
+
version: 0.7.7
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- David Heinemeier Hansson
|
|
@@ -10,34 +10,34 @@ authors:
|
|
|
10
10
|
autorequire:
|
|
11
11
|
bindir: bin
|
|
12
12
|
cert_chain: []
|
|
13
|
-
date: 2016-
|
|
13
|
+
date: 2016-08-18 00:00:00.000000000 Z
|
|
14
14
|
dependencies:
|
|
15
15
|
- !ruby/object:Gem::Dependency
|
|
16
16
|
name: activerecord
|
|
17
17
|
requirement: !ruby/object:Gem::Requirement
|
|
18
18
|
requirements:
|
|
19
|
-
- -
|
|
19
|
+
- - ">="
|
|
20
20
|
- !ruby/object:Gem::Version
|
|
21
21
|
version: '3.0'
|
|
22
22
|
type: :runtime
|
|
23
23
|
prerelease: false
|
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
|
25
25
|
requirements:
|
|
26
|
-
- -
|
|
26
|
+
- - ">="
|
|
27
27
|
- !ruby/object:Gem::Version
|
|
28
28
|
version: '3.0'
|
|
29
29
|
- !ruby/object:Gem::Dependency
|
|
30
30
|
name: bundler
|
|
31
31
|
requirement: !ruby/object:Gem::Requirement
|
|
32
32
|
requirements:
|
|
33
|
-
- -
|
|
33
|
+
- - ">="
|
|
34
34
|
- !ruby/object:Gem::Version
|
|
35
35
|
version: 1.0.0
|
|
36
36
|
type: :development
|
|
37
37
|
prerelease: false
|
|
38
38
|
version_requirements: !ruby/object:Gem::Requirement
|
|
39
39
|
requirements:
|
|
40
|
-
- -
|
|
40
|
+
- - ">="
|
|
41
41
|
- !ruby/object:Gem::Version
|
|
42
42
|
version: 1.0.0
|
|
43
43
|
description: This "acts_as" extension provides the capabilities for sorting and reordering
|
|
@@ -49,9 +49,9 @@ executables: []
|
|
|
49
49
|
extensions: []
|
|
50
50
|
extra_rdoc_files: []
|
|
51
51
|
files:
|
|
52
|
-
- .gemtest
|
|
53
|
-
- .gitignore
|
|
54
|
-
- .travis.yml
|
|
52
|
+
- ".gemtest"
|
|
53
|
+
- ".gitignore"
|
|
54
|
+
- ".travis.yml"
|
|
55
55
|
- Appraisals
|
|
56
56
|
- CHANGELOG.md
|
|
57
57
|
- Gemfile
|
|
@@ -62,6 +62,7 @@ files:
|
|
|
62
62
|
- gemfiles/rails_3_2.gemfile
|
|
63
63
|
- gemfiles/rails_4_1.gemfile
|
|
64
64
|
- gemfiles/rails_4_2.gemfile
|
|
65
|
+
- gemfiles/rails_5_0.gemfile
|
|
65
66
|
- init.rb
|
|
66
67
|
- lib/acts_as_list.rb
|
|
67
68
|
- lib/acts_as_list/active_record/acts/list.rb
|
|
@@ -72,8 +73,10 @@ files:
|
|
|
72
73
|
- test/shared_list.rb
|
|
73
74
|
- test/shared_list_sub.rb
|
|
74
75
|
- test/shared_no_addition.rb
|
|
76
|
+
- test/shared_quoting.rb
|
|
75
77
|
- test/shared_top_addition.rb
|
|
76
78
|
- test/shared_zero_based.rb
|
|
79
|
+
- test/test_joined_list.rb
|
|
77
80
|
- test/test_list.rb
|
|
78
81
|
homepage: http://github.com/swanandp/acts_as_list
|
|
79
82
|
licenses:
|
|
@@ -85,12 +88,12 @@ require_paths:
|
|
|
85
88
|
- lib
|
|
86
89
|
required_ruby_version: !ruby/object:Gem::Requirement
|
|
87
90
|
requirements:
|
|
88
|
-
- -
|
|
91
|
+
- - ">="
|
|
89
92
|
- !ruby/object:Gem::Version
|
|
90
93
|
version: 1.9.2
|
|
91
94
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
92
95
|
requirements:
|
|
93
|
-
- -
|
|
96
|
+
- - ">="
|
|
94
97
|
- !ruby/object:Gem::Version
|
|
95
98
|
version: '0'
|
|
96
99
|
requirements: []
|
|
@@ -107,6 +110,8 @@ test_files:
|
|
|
107
110
|
- test/shared_list.rb
|
|
108
111
|
- test/shared_list_sub.rb
|
|
109
112
|
- test/shared_no_addition.rb
|
|
113
|
+
- test/shared_quoting.rb
|
|
110
114
|
- test/shared_top_addition.rb
|
|
111
115
|
- test/shared_zero_based.rb
|
|
116
|
+
- test/test_joined_list.rb
|
|
112
117
|
- test/test_list.rb
|