acts_as_list 0.9.5 → 0.9.6

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: 66daa5cd56691f7a638ae9dd8f1a9c3feec0577c
4
- data.tar.gz: 7574120085bc23b698489eeb890112df78dd7689
3
+ metadata.gz: 5be2da067217f4dab82cf86a51c149578b3839ff
4
+ data.tar.gz: ead2d7fc41857aa193f37d0f8cbd5bffbe052462
5
5
  SHA512:
6
- metadata.gz: acad50db58bda1347963b54c71929bf9d79fce33e47b3efc0c3d7f2ffe17a370ff984c3ff83796e3a31350ec10fce07d2448d95adf796cf1661166070f06ada6
7
- data.tar.gz: 7d3bdb848e5a1bc50ed1b5e620eaaaa940cb956a23f1fc12649ca1fab410a2dd3d9df8e0190fd6229ec69048c0066fad59d86d5f48ef07b8e2602d3b1bcf4ee8
6
+ metadata.gz: fa9338e297f70fc50afd3d1ad6bf4d933883f0626f6f85a2ef79543255a4191df222a90e9b683edc95d3f613f27135538de0dc795086144e7d6bcbc4404c87a9
7
+ data.tar.gz: 02f13a0c906e75a3fe32341bcaa6237c3ba4ba258bbf80809a7cc332dffb0e1d90e3ab1047335ad46f6f315a3daf2b46dadc44959d791009617588d849f99988
@@ -1,5 +1,18 @@
1
1
  # Change Log
2
2
 
3
+ ## [v0.9.5](https://github.com/swanandp/acts_as_list/tree/v0.9.5) (2017-04-04)
4
+ [Full Changelog](https://github.com/swanandp/acts_as_list/compare/v0.9.4...v0.9.5)
5
+
6
+ **Closed issues:**
7
+
8
+ - acts\_as\_list\_class.maximum\(position\_column\) is causing the entire table to lock [\#264](https://github.com/swanandp/acts_as_list/issues/264)
9
+ - Be more precise with unscope-ing [\#263](https://github.com/swanandp/acts_as_list/issues/263)
10
+
11
+ **Merged pull requests:**
12
+
13
+ - Use bottom\_position\_in\_list instead of the highest value in the table [\#266](https://github.com/swanandp/acts_as_list/pull/266) ([brendon](https://github.com/brendon))
14
+ - Be more surgical about unscoping [\#265](https://github.com/swanandp/acts_as_list/pull/265) ([brendon](https://github.com/brendon))
15
+
3
16
  ## [v0.9.4](https://github.com/swanandp/acts_as_list/tree/v0.9.4) (2017-03-16)
4
17
  [Full Changelog](https://github.com/swanandp/acts_as_list/compare/v0.9.3...v0.9.4)
5
18
 
@@ -24,6 +24,6 @@ Gem::Specification.new do |s|
24
24
 
25
25
 
26
26
  # Dependencies (installed via "bundle install")
27
- s.add_dependency("activerecord", [">= 3.0"])
28
- s.add_development_dependency("bundler", [">= 1.0.0"])
27
+ s.add_dependency "activerecord", ">= 3.0"
28
+ s.add_development_dependency "bundler", ">= 1.0.0"
29
29
  end
@@ -1,9 +1,10 @@
1
- require 'acts_as_list/active_record/acts/list'
1
+ require "acts_as_list/active_record/acts/list"
2
2
  require "acts_as_list/active_record/acts/position_column_method_definer"
3
3
  require "acts_as_list/active_record/acts/scope_method_definer"
4
4
  require "acts_as_list/active_record/acts/top_of_list_method_definer"
5
5
  require "acts_as_list/active_record/acts/add_new_at_method_definer"
6
6
  require "acts_as_list/active_record/acts/aux_method_definer"
7
7
  require "acts_as_list/active_record/acts/callback_definer"
8
- require 'acts_as_list/active_record/acts/no_update'
8
+ require "acts_as_list/active_record/acts/no_update"
9
9
  require "acts_as_list/active_record/acts/sequential_updates_method_definer"
10
+ require "acts_as_list/active_record/acts/active_record"
@@ -0,0 +1,3 @@
1
+ ActiveSupport.on_load :active_record do
2
+ extend ActiveRecord::Acts::List::ClassMethods
3
+ end
@@ -1,64 +1,66 @@
1
- class << ActiveRecord::Base
2
- # Configuration options are:
3
- #
4
- # * +column+ - specifies the column name to use for keeping the position integer (default: +position+)
5
- # * +scope+ - restricts what is to be considered a list. Given a symbol, it'll attach <tt>_id</tt>
6
- # (if it hasn't already been added) and use that as the foreign key restriction. It's also possible
7
- # to give it an entire string that is interpolated if you need a tighter scope than just a foreign key.
8
- # Example: <tt>acts_as_list scope: 'todo_list_id = #{todo_list_id} AND completed = 0'</tt>
9
- # * +top_of_list+ - defines the integer used for the top of the list. Defaults to 1. Use 0 to make the collection
10
- # act more like an array in its indexing.
11
- # * +add_new_at+ - specifies whether objects get added to the :top or :bottom of the list. (default: +bottom+)
12
- # `nil` will result in new items not being added to the list on create.
13
- # * +sequential_updates+ - specifies whether insert_at should update objects positions during shuffling
14
- # one by one to respect position column unique not null constraint.
15
- # Defaults to true if position column has unique index, otherwise false.
16
- # If constraint is <tt>deferrable initially deferred<tt>, overriding it with false will speed up insert_at.
17
- def acts_as_list(options = {})
18
- configuration = { column: "position", scope: "1 = 1", top_of_list: 1, add_new_at: :bottom }
19
- configuration.update(options) if options.is_a?(Hash)
20
-
21
- caller_class = self
22
-
23
- ActiveRecord::Acts::List::PositionColumnMethodDefiner.call(caller_class, configuration[:column])
24
- ActiveRecord::Acts::List::ScopeMethodDefiner.call(caller_class, configuration[:scope])
25
- ActiveRecord::Acts::List::TopOfListMethodDefiner.call(caller_class, configuration[:top_of_list])
26
- ActiveRecord::Acts::List::AddNewAtMethodDefiner.call(caller_class, configuration[:add_new_at])
27
-
28
- ActiveRecord::Acts::List::AuxMethodDefiner.call(caller_class)
29
- ActiveRecord::Acts::List::CallbackDefiner.call(caller_class, configuration[:add_new_at])
30
- ActiveRecord::Acts::List::SequentialUpdatesMethodDefiner.call(caller_class, configuration[:column], configuration[:sequential_updates])
31
-
32
- include ActiveRecord::Acts::List::InstanceMethods
33
- include ActiveRecord::Acts::List::NoUpdate
34
- end
35
- end
36
-
37
1
  module ActiveRecord
38
2
  module Acts #:nodoc:
39
3
  module List #:nodoc:
40
- # This +acts_as+ extension provides the capabilities for sorting and reordering a number of objects in a list.
41
- # The class that has this specified needs to have a +position+ column defined as an integer on
42
- # the mapped database table.
43
- #
44
- # Todo list example:
45
- #
46
- # class TodoList < ActiveRecord::Base
47
- # has_many :todo_items, order: "position"
48
- # end
49
- #
50
- # class TodoItem < ActiveRecord::Base
51
- # belongs_to :todo_list
52
- # acts_as_list scope: :todo_list
53
- # end
54
- #
55
- # todo_list.first.move_to_bottom
56
- # todo_list.last.move_higher
57
-
58
- # All the methods available to a record that has had <tt>acts_as_list</tt> specified. Each method works
59
- # by assuming the object to be the item in the list, so <tt>chapter.move_lower</tt> would move that chapter
60
- # lower in the list of all chapters. Likewise, <tt>chapter.first?</tt> would return +true+ if that chapter is
61
- # the first in the list of all chapters.
4
+
5
+ module ClassMethods
6
+ # Configuration options are:
7
+ #
8
+ # * +column+ - specifies the column name to use for keeping the position integer (default: +position+)
9
+ # * +scope+ - restricts what is to be considered a list. Given a symbol, it'll attach <tt>_id</tt>
10
+ # (if it hasn't already been added) and use that as the foreign key restriction. It's also possible
11
+ # to give it an entire string that is interpolated if you need a tighter scope than just a foreign key.
12
+ # Example: <tt>acts_as_list scope: 'todo_list_id = #{todo_list_id} AND completed = 0'</tt>
13
+ # * +top_of_list+ - defines the integer used for the top of the list. Defaults to 1. Use 0 to make the collection
14
+ # act more like an array in its indexing.
15
+ # * +add_new_at+ - specifies whether objects get added to the :top or :bottom of the list. (default: +bottom+)
16
+ # `nil` will result in new items not being added to the list on create.
17
+ # * +sequential_updates+ - specifies whether insert_at should update objects positions during shuffling
18
+ # one by one to respect position column unique not null constraint.
19
+ # Defaults to true if position column has unique index, otherwise false.
20
+ # If constraint is <tt>deferrable initially deferred<tt>, overriding it with false will speed up insert_at.
21
+ def acts_as_list(options = {})
22
+ configuration = { column: "position", scope: "1 = 1", top_of_list: 1, add_new_at: :bottom }
23
+ configuration.update(options) if options.is_a?(Hash)
24
+
25
+ caller_class = self
26
+
27
+ ActiveRecord::Acts::List::PositionColumnMethodDefiner.call(caller_class, configuration[:column])
28
+ ActiveRecord::Acts::List::ScopeMethodDefiner.call(caller_class, configuration[:scope])
29
+ ActiveRecord::Acts::List::TopOfListMethodDefiner.call(caller_class, configuration[:top_of_list])
30
+ ActiveRecord::Acts::List::AddNewAtMethodDefiner.call(caller_class, configuration[:add_new_at])
31
+
32
+ ActiveRecord::Acts::List::AuxMethodDefiner.call(caller_class)
33
+ ActiveRecord::Acts::List::CallbackDefiner.call(caller_class, configuration[:add_new_at])
34
+ ActiveRecord::Acts::List::SequentialUpdatesMethodDefiner.call(caller_class, configuration[:column], configuration[:sequential_updates])
35
+
36
+ include ActiveRecord::Acts::List::InstanceMethods
37
+ include ActiveRecord::Acts::List::NoUpdate
38
+ end
39
+
40
+ # This +acts_as+ extension provides the capabilities for sorting and reordering a number of objects in a list.
41
+ # The class that has this specified needs to have a +position+ column defined as an integer on
42
+ # the mapped database table.
43
+ #
44
+ # Todo list example:
45
+ #
46
+ # class TodoList < ActiveRecord::Base
47
+ # has_many :todo_items, order: "position"
48
+ # end
49
+ #
50
+ # class TodoItem < ActiveRecord::Base
51
+ # belongs_to :todo_list
52
+ # acts_as_list scope: :todo_list
53
+ # end
54
+ #
55
+ # todo_list.first.move_to_bottom
56
+ # todo_list.last.move_higher
57
+
58
+ # All the methods available to a record that has had <tt>acts_as_list</tt> specified. Each method works
59
+ # by assuming the object to be the item in the list, so <tt>chapter.move_lower</tt> would move that chapter
60
+ # lower in the list of all chapters. Likewise, <tt>chapter.first?</tt> would return +true+ if that chapter is
61
+ # the first in the list of all chapters.
62
+ end
63
+
62
64
  module InstanceMethods
63
65
  # Insert the item at the given position (defaults to the top position of 1).
64
66
  def insert_at(position = acts_as_list_top)
@@ -376,7 +378,7 @@ module ActiveRecord
376
378
  end
377
379
  end
378
380
  end
379
-
381
+
380
382
  def insert_at_position(position)
381
383
  return set_list_position(position) if new_record?
382
384
  with_lock do
@@ -408,7 +410,7 @@ module ActiveRecord
408
410
 
409
411
  def position_before_save
410
412
  if ActiveRecord::VERSION::MAJOR == 5 && ActiveRecord::VERSION::MINOR >= 1 ||
411
- ActiveRecord::VERSION::MAJOR > 5
413
+ ActiveRecord::VERSION::MAJOR > 5
412
414
 
413
415
  send("#{position_column}_before_last_save")
414
416
  else
@@ -430,9 +432,9 @@ module ActiveRecord
430
432
  if internal_scope_changed?
431
433
  cached_changes = changes
432
434
 
433
- cached_changes.each { |attribute, values| self[attribute] = values[0] }
435
+ cached_changes.each { |attribute, values| send("#{attribute}=", values[0]) }
434
436
  send('decrement_positions_on_lower_items') if lower_item
435
- cached_changes.each { |attribute, values| self[attribute] = values[1] }
437
+ cached_changes.each { |attribute, values| send("#{attribute}=", values[1]) }
436
438
 
437
439
  send("add_to_list_#{add_new_at}") if add_new_at.present?
438
440
  end
@@ -460,6 +462,7 @@ module ActiveRecord
460
462
  @_quoted_position_column_with_table_name ||= "#{quoted_table_name}.#{quoted_position_column}"
461
463
  end
462
464
  end
465
+
463
466
  end
464
467
  end
465
468
  end
@@ -2,7 +2,10 @@ module ActiveRecord
2
2
  module Acts
3
3
  module List
4
4
  module NoUpdate
5
- extend ActiveSupport::Concern
5
+
6
+ def self.included(base)
7
+ base.extend ClassMethods
8
+ end
6
9
 
7
10
  class ArrayTypeError < SyntaxError
8
11
  def initialize
@@ -96,9 +99,9 @@ module ActiveRecord
96
99
 
97
100
  private
98
101
 
99
- def extracted_klasses
100
- Thread.current[:act_as_list_no_update] ||= []
101
- end
102
+ def extracted_klasses
103
+ Thread.current[:act_as_list_no_update] ||= []
104
+ end
102
105
  end
103
106
 
104
107
  def act_as_list_no_update?
@@ -29,15 +29,13 @@ module ActiveRecord::Acts::List::PositionColumnMethodDefiner #:nodoc:
29
29
  end
30
30
 
31
31
  define_singleton_method :update_all_with_touch do |updates|
32
- record = new
33
- attrs = record.send(:timestamp_attributes_for_update_in_model)
34
- now = record.send(:current_time_from_proper_timezone)
32
+ update_all(updates << touch_record_sql)
33
+ end
35
34
 
36
- attrs.each do |attr|
37
- updates << ", #{connection.quote_column_name(attr)} = #{connection.quote(connection.quoted_date(now))}"
38
- end
35
+ private
39
36
 
40
- update_all(updates)
37
+ define_singleton_method :touch_record_sql do
38
+ new.touch_record_sql
41
39
  end
42
40
  end
43
41
  end
@@ -54,6 +52,23 @@ module ActiveRecord::Acts::List::PositionColumnMethodDefiner #:nodoc:
54
52
  write_attribute(position_column, position)
55
53
  @position_changed = true
56
54
  end
55
+
56
+ define_method :touch_record_sql do
57
+ cached_quoted_now = quoted_current_time_from_proper_timezone
58
+
59
+ timestamp_attributes_for_update_in_model.map do |attr|
60
+ ", #{connection.quote_column_name(attr)} = #{cached_quoted_now}"
61
+ end.join
62
+ end
63
+
64
+ private
65
+
66
+ delegate :connection, to: self
67
+
68
+ def quoted_current_time_from_proper_timezone
69
+ connection.quote(connection.quoted_date(
70
+ current_time_from_proper_timezone))
71
+ end
57
72
  end
58
73
  end
59
74
 
@@ -1,7 +1,7 @@
1
1
  module ActiveRecord
2
2
  module Acts
3
3
  module List
4
- VERSION = '0.9.5'
4
+ VERSION = '0.9.6'
5
5
  end
6
6
  end
7
7
  end
@@ -62,7 +62,7 @@ module Shared
62
62
 
63
63
  new = ArrayScopeListMixin.acts_as_list_no_update { ArrayScopeListMixin.create(parent_id: 20, parent_type: 'ParentClass') }
64
64
  assert_equal_or_nil $default_position,new.pos
65
- assert_equal $default_position.is_a?(Fixnum), new.first?
65
+ assert_equal $default_position.is_a?(Integer), new.first?
66
66
  assert !new.last?
67
67
 
68
68
  new = ArrayScopeListMixin.create(parent_id: 20, parent_type: 'ParentClass')
@@ -62,7 +62,7 @@ module Shared
62
62
 
63
63
  new = ListMixin.acts_as_list_no_update { ListMixin.create(parent_id: 20) }
64
64
  assert_equal_or_nil $default_position, new.pos
65
- assert_equal $default_position.is_a?(Fixnum), new.first?
65
+ assert_equal $default_position.is_a?(Integer), new.first?
66
66
  assert !new.last?
67
67
 
68
68
  new = ListMixin.create(parent_id: 20)
@@ -48,7 +48,7 @@ module Shared
48
48
 
49
49
  new = TopAdditionMixin.acts_as_list_no_update { TopAdditionMixin.create(parent_id: 20) }
50
50
  assert_equal_or_nil $default_position, new.pos
51
- assert_equal $default_position.is_a?(Fixnum), new.first?
51
+ assert_equal $default_position.is_a?(Integer), new.first?
52
52
  assert !new.last?
53
53
 
54
54
  new = TopAdditionMixin.create(parent_id: 20)
@@ -327,7 +327,7 @@ class DefaultScopedTest < ActsAsListTestCase
327
327
 
328
328
  new = DefaultScopedMixin.acts_as_list_no_update { DefaultScopedMixin.create }
329
329
  assert_equal_or_nil $default_position, new.pos
330
- assert_equal $default_position.is_a?(Fixnum), new.first?
330
+ assert_equal $default_position.is_a?(Integer), new.first?
331
331
  assert !new.last?
332
332
 
333
333
  new = DefaultScopedMixin.create
@@ -431,7 +431,7 @@ class DefaultScopedWhereTest < ActsAsListTestCase
431
431
 
432
432
  new = DefaultScopedWhereMixin.acts_as_list_no_update { DefaultScopedWhereMixin.create }
433
433
  assert_equal_or_nil $default_position, new.pos
434
- assert_equal $default_position.is_a?(Fixnum), new.first?
434
+ assert_equal $default_position.is_a?(Integer), new.first?
435
435
  assert !new.last?
436
436
 
437
437
  new = DefaultScopedWhereMixin.create
@@ -641,6 +641,12 @@ if rails_4
641
641
  assert_equal [1], EnumArrayScopeListMixin.where(:parent_id => 2, :state => EnumArrayScopeListMixin.states['active']).map(&:pos)
642
642
  assert_equal [1], EnumArrayScopeListMixin.where(:parent_id => 2, :state => EnumArrayScopeListMixin.states['archived']).map(&:pos)
643
643
  end
644
+
645
+ def test_update_state
646
+ active_item = EnumArrayScopeListMixin.find_by(:parent_id => 2, :state => EnumArrayScopeListMixin.states['active'])
647
+ active_item.update(state: EnumArrayScopeListMixin.states['archived'])
648
+ assert_equal [1, 2], EnumArrayScopeListMixin.where(:parent_id => 2, :state => EnumArrayScopeListMixin.states['archived']).map(&:pos).sort
649
+ end
644
650
  end
645
651
  end
646
652
 
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.9.5
4
+ version: 0.9.6
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: 2017-04-04 00:00:00.000000000 Z
13
+ date: 2017-07-05 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activerecord
@@ -66,6 +66,7 @@ files:
66
66
  - gemfiles/rails_5_1.gemfile
67
67
  - init.rb
68
68
  - lib/acts_as_list.rb
69
+ - lib/acts_as_list/active_record/acts/active_record.rb
69
70
  - lib/acts_as_list/active_record/acts/add_new_at_method_definer.rb
70
71
  - lib/acts_as_list/active_record/acts/aux_method_definer.rb
71
72
  - lib/acts_as_list/active_record/acts/callback_definer.rb