acts_as_list 0.7.6 → 0.7.7
Sign up to get free protection for your applications and to get access to all the features.
- 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
|