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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ac758ea2c45c36f2da4a70277a4e359e32cbebec
4
- data.tar.gz: 44cb219c5932187141cb11cb774e2165b9be86f0
3
+ metadata.gz: d62dacdeb7972152a2ee04cee3cccb8ef26898d7
4
+ data.tar.gz: fe6b02bfa1c5ed33407d1852c7b988a1848c7cd4
5
5
  SHA512:
6
- metadata.gz: 32474515db63aa64fea168c43654ebc2d86e24ad5bba2e1e793b0a484ff6d0e40d880c62d559fdf5d830b4213f9ca4a56f5ab776e102daf28e86a1ee1e772dbb
7
- data.tar.gz: ab9e2ae5dbe3313a1b69f8cb82019494a10bce07c0343acc88062cd8475774dc2202fa8104cbb156797aae53b87631cabe8766cdf0f627eac7296934ae5dd50b
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.21"
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.10"
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.1"
16
+ gem "activerecord", "~> 4.2.7"
11
17
  end
12
18
 
13
19
  appraise "rails-5-0" do
14
- gem "activerecord", "~> 5.0.0.rc2"
20
+ gem "activerecord", "~> 5.0.0"
15
21
  end
@@ -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
- # Specify your gem"s dependencies in acts_as_list-rails3.gemspec
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
@@ -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.21"
11
+ gem "activerecord", "~> 3.2.22.2"
11
12
 
12
13
  group :test do
13
14
  gem "minitest", "~> 5.0"
@@ -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.10"
11
+ gem "activerecord", "~> 4.1.16"
11
12
 
12
13
  group :test do
13
14
  gem "minitest", "~> 5.0"
@@ -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.1"
11
+ gem "activerecord", "~> 4.2.7"
11
12
 
12
13
  group :test do
13
14
  gem "minitest", "~> 5.0"
@@ -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.beta3"
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{#{quoted_table_name}.#{quoted_position_column} IS NOT NULL}) }
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} = (#{quoted_table_name}.#{quoted_position_column} - 1))
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} = (#{quoted_table_name}.#{quoted_position_column} + 1))
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("#{quoted_table_name}.#{quoted_position_column} < ?", position_value).
263
- where("#{quoted_table_name}.#{quoted_position_column} >= ?", position_value - limit).
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("#{quoted_table_name}.#{quoted_position_column} ASC")
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("#{quoted_table_name}.#{quoted_position_column} > ?", position_value).
281
- where("#{quoted_table_name}.#{quoted_position_column} <= ?", position_value + limit).
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("#{quoted_table_name}.#{quoted_position_column} ASC")
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
- "#{quoted_table_name}.#{quoted_position_column} DESC"
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("#{quoted_position_column} <= #{position}").decrement_all
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("#{quoted_position_column} > #{position}").decrement_all
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("#{quoted_position_column} < #{send(position_column).to_i}").increment_all
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("#{quoted_position_column} >= #{position}#{avoid_id_condition}").increment_all
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
- "#{quoted_position_column} > #{old_position}"
413
+ "#{quoted_position_column_with_table_name} > ?", old_position
413
414
  ).where(
414
- "#{quoted_position_column} <= #{new_position}#{avoid_id_condition}"
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
- "#{quoted_position_column} >= #{new_position}"
423
+ "#{quoted_position_column_with_table_name} >= ?", new_position
423
424
  ).where(
424
- "#{quoted_position_column} < #{old_position}#{avoid_id_condition}"
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
- if in_list?
432
- old_position = send(position_column).to_i
433
- return if position == old_position
434
- shuffle_positions_on_intermediate_items(old_position, position)
435
- else
436
- increment_positions_on_lower_items(position)
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
- "#{quoted_position_column} = #{new_position}"
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
@@ -1,7 +1,7 @@
1
1
  module ActiveRecord
2
2
  module Acts
3
3
  module List
4
- VERSION = '0.7.6'
4
+ VERSION = '0.7.7'
5
5
  end
6
6
  end
7
7
  end
@@ -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
@@ -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(adapter: "sqlite3", database: ":memory:")
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.6
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-07-15 00:00:00.000000000 Z
13
+ date: 2016-08-18 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activerecord