acts_as_list 0.7.5 → 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 +4 -4
- data/Appraisals +10 -4
- data/CHANGELOG.md +55 -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 +2 -1
- data/lib/acts_as_list/active_record/acts/list.rb +43 -32
- data/lib/acts_as_list/version.rb +1 -1
- data/test/shared_list.rb +6 -0
- data/test/shared_no_addition.rb +11 -0
- data/test/test_list.rb +58 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d62dacdeb7972152a2ee04cee3cccb8ef26898d7
|
|
4
|
+
data.tar.gz: fe6b02bfa1c5ed33407d1852c7b988a1848c7cd4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6b376b14646463802f4aee7080663eefdb3d7b1a43088df7126f57c84ecfb0a8730470efe4b57758f2b2079d6bd52b19f2a80293b211095318425d5892194897
|
|
7
|
+
data.tar.gz: fa104b99749d08767074e96f5fea1e97590ee841673660c39d03bb3d2cd50a3d2db2de4d1d195d5503d1bfadec7cbe84e046714f0ab98d0d509bc4c4797949e2
|
data/Appraisals
CHANGED
|
@@ -1,15 +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"
|
|
11
17
|
end
|
|
12
18
|
|
|
13
19
|
appraise "rails-5-0" do
|
|
14
|
-
gem "activerecord", "~> 5.0.0
|
|
20
|
+
gem "activerecord", "~> 5.0.0"
|
|
15
21
|
end
|
data/CHANGELOG.md
CHANGED
|
@@ -1,12 +1,65 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
-
## [
|
|
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)
|
|
4
5
|
|
|
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))
|
|
6
21
|
|
|
7
22
|
**Closed issues:**
|
|
8
23
|
|
|
24
|
+
- Exception raised when calling destroy "NameError - instance variable @scope\_changed not defined:" [\#206](https://github.com/swanandp/acts_as_list/issues/206)
|
|
9
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))
|
|
10
63
|
|
|
11
64
|
## [v0.7.4](https://github.com/swanandp/acts_as_list/tree/v0.7.4) (2016-04-15)
|
|
12
65
|
[Full Changelog](https://github.com/swanandp/acts_as_list/compare/v0.7.3...v0.7.4)
|
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"
|
data/gemfiles/rails_5_0.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", "~> 5.0.0
|
|
11
|
+
gem "activerecord", "~> 5.0.0"
|
|
11
12
|
|
|
12
13
|
group :test do
|
|
13
14
|
gem "minitest", "~> 5.0"
|
|
@@ -75,8 +75,13 @@ module ActiveRecord
|
|
|
75
75
|
end
|
|
76
76
|
|
|
77
77
|
quoted_position_column = connection.quote_column_name(configuration[:column])
|
|
78
|
+
quoted_position_column_with_table_name = "#{quoted_table_name}.#{quoted_position_column}"
|
|
78
79
|
|
|
79
80
|
class_eval <<-EOV, __FILE__, __LINE__ + 1
|
|
81
|
+
def self.acts_as_list_top
|
|
82
|
+
#{configuration[:top_of_list]}.to_i
|
|
83
|
+
end
|
|
84
|
+
|
|
80
85
|
def acts_as_list_top
|
|
81
86
|
#{configuration[:top_of_list]}.to_i
|
|
82
87
|
end
|
|
@@ -111,14 +116,14 @@ module ActiveRecord
|
|
|
111
116
|
attr_accessible :#{configuration[:column]}
|
|
112
117
|
end
|
|
113
118
|
|
|
114
|
-
scope :in_list, lambda { where(%q{#{
|
|
119
|
+
scope :in_list, lambda { where(%q{#{quoted_position_column_with_table_name} IS NOT NULL}) }
|
|
115
120
|
|
|
116
121
|
def self.decrement_all
|
|
117
|
-
update_all_with_touch %q(#{quoted_position_column} = (#{
|
|
122
|
+
update_all_with_touch %q(#{quoted_position_column} = (#{quoted_position_column_with_table_name} - 1))
|
|
118
123
|
end
|
|
119
124
|
|
|
120
125
|
def self.increment_all
|
|
121
|
-
update_all_with_touch %q(#{quoted_position_column} = (#{
|
|
126
|
+
update_all_with_touch %q(#{quoted_position_column} = (#{quoted_position_column_with_table_name} + 1))
|
|
122
127
|
end
|
|
123
128
|
|
|
124
129
|
def self.update_all_with_touch(updates)
|
|
@@ -137,10 +142,10 @@ module ActiveRecord
|
|
|
137
142
|
attr_reader :position_changed
|
|
138
143
|
|
|
139
144
|
before_validation :check_top_position
|
|
140
|
-
|
|
145
|
+
|
|
141
146
|
before_destroy :lock!
|
|
142
147
|
after_destroy :decrement_positions_on_lower_items
|
|
143
|
-
|
|
148
|
+
|
|
144
149
|
before_update :check_scope
|
|
145
150
|
after_update :update_positions
|
|
146
151
|
|
|
@@ -255,10 +260,10 @@ module ActiveRecord
|
|
|
255
260
|
limit ||= acts_as_list_list.count
|
|
256
261
|
position_value = send(position_column)
|
|
257
262
|
acts_as_list_list.
|
|
258
|
-
where("#{
|
|
259
|
-
where("#{
|
|
263
|
+
where("#{quoted_position_column_with_table_name} < ?", position_value).
|
|
264
|
+
where("#{quoted_position_column_with_table_name} >= ?", position_value - limit).
|
|
260
265
|
limit(limit).
|
|
261
|
-
order("#{
|
|
266
|
+
order("#{quoted_position_column_with_table_name} ASC")
|
|
262
267
|
end
|
|
263
268
|
|
|
264
269
|
# Return the next lower item in the list.
|
|
@@ -273,10 +278,10 @@ module ActiveRecord
|
|
|
273
278
|
limit ||= acts_as_list_list.count
|
|
274
279
|
position_value = send(position_column)
|
|
275
280
|
acts_as_list_list.
|
|
276
|
-
where("#{
|
|
277
|
-
where("#{
|
|
281
|
+
where("#{quoted_position_column_with_table_name} > ?", position_value).
|
|
282
|
+
where("#{quoted_position_column_with_table_name} <= ?", position_value + limit).
|
|
278
283
|
limit(limit).
|
|
279
|
-
order("#{
|
|
284
|
+
order("#{quoted_position_column_with_table_name} ASC")
|
|
280
285
|
end
|
|
281
286
|
|
|
282
287
|
# Test if this record is in a list
|
|
@@ -346,11 +351,11 @@ module ActiveRecord
|
|
|
346
351
|
|
|
347
352
|
# Returns the bottom item
|
|
348
353
|
def bottom_item(except = nil)
|
|
349
|
-
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)}" : {}
|
|
350
355
|
acts_as_list_list.in_list.where(
|
|
351
356
|
conditions
|
|
352
357
|
).order(
|
|
353
|
-
"#{
|
|
358
|
+
"#{quoted_position_column_with_table_name} DESC"
|
|
354
359
|
).first
|
|
355
360
|
end
|
|
356
361
|
|
|
@@ -366,27 +371,27 @@ module ActiveRecord
|
|
|
366
371
|
|
|
367
372
|
# This has the effect of moving all the higher items up one.
|
|
368
373
|
def decrement_positions_on_higher_items(position)
|
|
369
|
-
acts_as_list_list.where("#{
|
|
374
|
+
acts_as_list_list.where("#{quoted_position_column_with_table_name} <= ?", position).decrement_all
|
|
370
375
|
end
|
|
371
376
|
|
|
372
377
|
# This has the effect of moving all the lower items up one.
|
|
373
378
|
def decrement_positions_on_lower_items(position=nil)
|
|
374
379
|
return unless in_list?
|
|
375
380
|
position ||= send(position_column).to_i
|
|
376
|
-
acts_as_list_list.where("#{
|
|
381
|
+
acts_as_list_list.where("#{quoted_position_column_with_table_name} > ?", position).decrement_all
|
|
377
382
|
end
|
|
378
383
|
|
|
379
384
|
# This has the effect of moving all the higher items down one.
|
|
380
385
|
def increment_positions_on_higher_items
|
|
381
386
|
return unless in_list?
|
|
382
|
-
acts_as_list_list.where("#{
|
|
387
|
+
acts_as_list_list.where("#{quoted_position_column_with_table_name} < #{send(position_column).to_i}").increment_all
|
|
383
388
|
end
|
|
384
389
|
|
|
385
390
|
# This has the effect of moving all the lower items down one.
|
|
386
391
|
def increment_positions_on_lower_items(position, avoid_id = nil)
|
|
387
|
-
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)}" : ''
|
|
388
393
|
|
|
389
|
-
acts_as_list_list.where("#{
|
|
394
|
+
acts_as_list_list.where("#{quoted_position_column_with_table_name} >= #{position}#{avoid_id_condition}").increment_all
|
|
390
395
|
end
|
|
391
396
|
|
|
392
397
|
# Increments position (<tt>position_column</tt>) of all items in the list.
|
|
@@ -397,7 +402,7 @@ module ActiveRecord
|
|
|
397
402
|
# Reorders intermediate items to support moving an item from old_position to new_position.
|
|
398
403
|
def shuffle_positions_on_intermediate_items(old_position, new_position, avoid_id = nil)
|
|
399
404
|
return if old_position == new_position
|
|
400
|
-
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)}" : ''
|
|
401
406
|
|
|
402
407
|
if old_position < new_position
|
|
403
408
|
# Decrement position of intermediate items
|
|
@@ -405,9 +410,9 @@ module ActiveRecord
|
|
|
405
410
|
# e.g., if moving an item from 2 to 5,
|
|
406
411
|
# move [3, 4, 5] to [2, 3, 4]
|
|
407
412
|
acts_as_list_list.where(
|
|
408
|
-
"#{
|
|
413
|
+
"#{quoted_position_column_with_table_name} > ?", old_position
|
|
409
414
|
).where(
|
|
410
|
-
"#{
|
|
415
|
+
"#{quoted_position_column_with_table_name} <= #{new_position}#{avoid_id_condition}"
|
|
411
416
|
).decrement_all
|
|
412
417
|
else
|
|
413
418
|
# Increment position of intermediate items
|
|
@@ -415,23 +420,25 @@ module ActiveRecord
|
|
|
415
420
|
# e.g., if moving an item from 5 to 2,
|
|
416
421
|
# move [2, 3, 4] to [3, 4, 5]
|
|
417
422
|
acts_as_list_list.where(
|
|
418
|
-
"#{
|
|
423
|
+
"#{quoted_position_column_with_table_name} >= ?", new_position
|
|
419
424
|
).where(
|
|
420
|
-
"#{
|
|
425
|
+
"#{quoted_position_column_with_table_name} < #{old_position}#{avoid_id_condition}"
|
|
421
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,7 +455,7 @@ 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
|
|
@@ -471,7 +478,7 @@ module ActiveRecord
|
|
|
471
478
|
send('decrement_positions_on_lower_items') if lower_item
|
|
472
479
|
cached_changes.each { |attribute, values| self[attribute] = values[1] }
|
|
473
480
|
|
|
474
|
-
send("add_to_list_#{add_new_at}")
|
|
481
|
+
send("add_to_list_#{add_new_at}") if add_new_at.present?
|
|
475
482
|
end
|
|
476
483
|
end
|
|
477
484
|
|
|
@@ -492,6 +499,10 @@ module ActiveRecord
|
|
|
492
499
|
def quoted_table_name
|
|
493
500
|
@_quoted_table_name ||= acts_as_list_class.quoted_table_name
|
|
494
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
|
|
495
506
|
end
|
|
496
507
|
end
|
|
497
508
|
end
|
data/lib/acts_as_list/version.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
|
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
|
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 = {})
|
|
@@ -160,6 +163,13 @@ end
|
|
|
160
163
|
class TheBaseSubclass < TheBaseClass
|
|
161
164
|
end
|
|
162
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
|
+
|
|
163
173
|
class QuotedList < ActiveRecord::Base
|
|
164
174
|
self.table_name = 'table-name'
|
|
165
175
|
acts_as_list column: :order
|
|
@@ -200,6 +210,37 @@ class ListTest < ActsAsListTestCase
|
|
|
200
210
|
setup_db
|
|
201
211
|
super
|
|
202
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
|
|
203
244
|
end
|
|
204
245
|
|
|
205
246
|
class ListWithCallbackTest < ActsAsListTestCase
|
|
@@ -691,3 +732,19 @@ class TouchTest < ActsAsListTestCase
|
|
|
691
732
|
end
|
|
692
733
|
end
|
|
693
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,7 +10,7 @@ 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
|