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 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