acts_as_list 0.7.6 → 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 +12 -0
- data/Gemfile +2 -2
- 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 +38 -31
- data/lib/acts_as_list/version.rb +1 -1
- data/test/shared_list.rb +6 -0
- data/test/test_list.rb +42 -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,5 +1,17 @@
|
|
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
|
+
|
3
15
|
## [v0.7.5](https://github.com/swanandp/acts_as_list/tree/v0.7.5) (2016-06-30)
|
4
16
|
[Full Changelog](https://github.com/swanandp/acts_as_list/compare/v0.7.4...v0.7.5)
|
5
17
|
|
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/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,6 +75,7 @@ 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
|
80
81
|
def self.acts_as_list_top
|
@@ -115,14 +116,14 @@ module ActiveRecord
|
|
115
116
|
attr_accessible :#{configuration[:column]}
|
116
117
|
end
|
117
118
|
|
118
|
-
scope :in_list, lambda { where(%q{#{
|
119
|
+
scope :in_list, lambda { where(%q{#{quoted_position_column_with_table_name} IS NOT NULL}) }
|
119
120
|
|
120
121
|
def self.decrement_all
|
121
|
-
update_all_with_touch %q(#{quoted_position_column} = (#{
|
122
|
+
update_all_with_touch %q(#{quoted_position_column} = (#{quoted_position_column_with_table_name} - 1))
|
122
123
|
end
|
123
124
|
|
124
125
|
def self.increment_all
|
125
|
-
update_all_with_touch %q(#{quoted_position_column} = (#{
|
126
|
+
update_all_with_touch %q(#{quoted_position_column} = (#{quoted_position_column_with_table_name} + 1))
|
126
127
|
end
|
127
128
|
|
128
129
|
def self.update_all_with_touch(updates)
|
@@ -141,10 +142,10 @@ module ActiveRecord
|
|
141
142
|
attr_reader :position_changed
|
142
143
|
|
143
144
|
before_validation :check_top_position
|
144
|
-
|
145
|
+
|
145
146
|
before_destroy :lock!
|
146
147
|
after_destroy :decrement_positions_on_lower_items
|
147
|
-
|
148
|
+
|
148
149
|
before_update :check_scope
|
149
150
|
after_update :update_positions
|
150
151
|
|
@@ -259,10 +260,10 @@ module ActiveRecord
|
|
259
260
|
limit ||= acts_as_list_list.count
|
260
261
|
position_value = send(position_column)
|
261
262
|
acts_as_list_list.
|
262
|
-
where("#{
|
263
|
-
where("#{
|
263
|
+
where("#{quoted_position_column_with_table_name} < ?", position_value).
|
264
|
+
where("#{quoted_position_column_with_table_name} >= ?", position_value - limit).
|
264
265
|
limit(limit).
|
265
|
-
order("#{
|
266
|
+
order("#{quoted_position_column_with_table_name} ASC")
|
266
267
|
end
|
267
268
|
|
268
269
|
# Return the next lower item in the list.
|
@@ -277,10 +278,10 @@ module ActiveRecord
|
|
277
278
|
limit ||= acts_as_list_list.count
|
278
279
|
position_value = send(position_column)
|
279
280
|
acts_as_list_list.
|
280
|
-
where("#{
|
281
|
-
where("#{
|
281
|
+
where("#{quoted_position_column_with_table_name} > ?", position_value).
|
282
|
+
where("#{quoted_position_column_with_table_name} <= ?", position_value + limit).
|
282
283
|
limit(limit).
|
283
|
-
order("#{
|
284
|
+
order("#{quoted_position_column_with_table_name} ASC")
|
284
285
|
end
|
285
286
|
|
286
287
|
# Test if this record is in a list
|
@@ -350,11 +351,11 @@ module ActiveRecord
|
|
350
351
|
|
351
352
|
# Returns the bottom item
|
352
353
|
def bottom_item(except = nil)
|
353
|
-
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)}" : {}
|
354
355
|
acts_as_list_list.in_list.where(
|
355
356
|
conditions
|
356
357
|
).order(
|
357
|
-
"#{
|
358
|
+
"#{quoted_position_column_with_table_name} DESC"
|
358
359
|
).first
|
359
360
|
end
|
360
361
|
|
@@ -370,27 +371,27 @@ module ActiveRecord
|
|
370
371
|
|
371
372
|
# This has the effect of moving all the higher items up one.
|
372
373
|
def decrement_positions_on_higher_items(position)
|
373
|
-
acts_as_list_list.where("#{
|
374
|
+
acts_as_list_list.where("#{quoted_position_column_with_table_name} <= ?", position).decrement_all
|
374
375
|
end
|
375
376
|
|
376
377
|
# This has the effect of moving all the lower items up one.
|
377
378
|
def decrement_positions_on_lower_items(position=nil)
|
378
379
|
return unless in_list?
|
379
380
|
position ||= send(position_column).to_i
|
380
|
-
acts_as_list_list.where("#{
|
381
|
+
acts_as_list_list.where("#{quoted_position_column_with_table_name} > ?", position).decrement_all
|
381
382
|
end
|
382
383
|
|
383
384
|
# This has the effect of moving all the higher items down one.
|
384
385
|
def increment_positions_on_higher_items
|
385
386
|
return unless in_list?
|
386
|
-
acts_as_list_list.where("#{
|
387
|
+
acts_as_list_list.where("#{quoted_position_column_with_table_name} < #{send(position_column).to_i}").increment_all
|
387
388
|
end
|
388
389
|
|
389
390
|
# This has the effect of moving all the lower items down one.
|
390
391
|
def increment_positions_on_lower_items(position, avoid_id = nil)
|
391
|
-
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)}" : ''
|
392
393
|
|
393
|
-
acts_as_list_list.where("#{
|
394
|
+
acts_as_list_list.where("#{quoted_position_column_with_table_name} >= #{position}#{avoid_id_condition}").increment_all
|
394
395
|
end
|
395
396
|
|
396
397
|
# Increments position (<tt>position_column</tt>) of all items in the list.
|
@@ -401,7 +402,7 @@ module ActiveRecord
|
|
401
402
|
# Reorders intermediate items to support moving an item from old_position to new_position.
|
402
403
|
def shuffle_positions_on_intermediate_items(old_position, new_position, avoid_id = nil)
|
403
404
|
return if old_position == new_position
|
404
|
-
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)}" : ''
|
405
406
|
|
406
407
|
if old_position < new_position
|
407
408
|
# Decrement position of intermediate items
|
@@ -409,9 +410,9 @@ module ActiveRecord
|
|
409
410
|
# e.g., if moving an item from 2 to 5,
|
410
411
|
# move [3, 4, 5] to [2, 3, 4]
|
411
412
|
acts_as_list_list.where(
|
412
|
-
"#{
|
413
|
+
"#{quoted_position_column_with_table_name} > ?", old_position
|
413
414
|
).where(
|
414
|
-
"#{
|
415
|
+
"#{quoted_position_column_with_table_name} <= #{new_position}#{avoid_id_condition}"
|
415
416
|
).decrement_all
|
416
417
|
else
|
417
418
|
# Increment position of intermediate items
|
@@ -419,23 +420,25 @@ module ActiveRecord
|
|
419
420
|
# e.g., if moving an item from 5 to 2,
|
420
421
|
# move [2, 3, 4] to [3, 4, 5]
|
421
422
|
acts_as_list_list.where(
|
422
|
-
"#{
|
423
|
+
"#{quoted_position_column_with_table_name} >= ?", new_position
|
423
424
|
).where(
|
424
|
-
"#{
|
425
|
+
"#{quoted_position_column_with_table_name} < #{old_position}#{avoid_id_condition}"
|
425
426
|
).increment_all
|
426
427
|
end
|
427
428
|
end
|
428
429
|
|
429
430
|
def insert_at_position(position)
|
430
431
|
return set_list_position(position) if new_record?
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
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)
|
437
441
|
end
|
438
|
-
set_list_position(position)
|
439
442
|
end
|
440
443
|
|
441
444
|
# used by insert_at_position instead of remove_from_list, as postgresql raises error if position_column has non-null constraint
|
@@ -452,7 +455,7 @@ module ActiveRecord
|
|
452
455
|
new_position = send(position_column).to_i
|
453
456
|
|
454
457
|
return unless acts_as_list_list.where(
|
455
|
-
"#{
|
458
|
+
"#{quoted_position_column_with_table_name} = #{new_position}"
|
456
459
|
).count > 1
|
457
460
|
shuffle_positions_on_intermediate_items old_position, new_position, id
|
458
461
|
end
|
@@ -496,6 +499,10 @@ module ActiveRecord
|
|
496
499
|
def quoted_table_name
|
497
500
|
@_quoted_table_name ||= acts_as_list_class.quoted_table_name
|
498
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
|
499
506
|
end
|
500
507
|
end
|
501
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/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
|
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
|