acts_as_ordered_tree 1.1.1 → 1.1.2
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.
- data/lib/acts_as_ordered_tree/instance_methods.rb +47 -30
- data/lib/acts_as_ordered_tree/version.rb +1 -1
- data/spec/acts_as_ordered_tree_spec.rb +26 -0
- data/spec/concurrency_support_spec.rb +4 -7
- data/spec/spec_helper.rb +1 -0
- data/spec/support/factories.rb +4 -0
- data/spec/support/models.rb +16 -0
- metadata +4 -4
@@ -306,6 +306,9 @@ module ActsAsOrderedTree
|
|
306
306
|
# nothing changed - quit
|
307
307
|
return if parent_id == parent_id_was && position == position_was
|
308
308
|
|
309
|
+
self.class.find(self, :lock => true)
|
310
|
+
self[position_column], self[parent_column] = position, parent_id
|
311
|
+
|
309
312
|
move_kind = case
|
310
313
|
when id_was && parent_id != parent_id_was then :move
|
311
314
|
when id_was && position != position_was then :reorder
|
@@ -363,7 +366,7 @@ module ActsAsOrderedTree
|
|
363
366
|
"THEN :depth " +
|
364
367
|
"ELSE #{depth_column} " +
|
365
368
|
"END" if depth_column)
|
366
|
-
]
|
369
|
+
]
|
367
370
|
|
368
371
|
conditions = arel[pk].eq(id).or(
|
369
372
|
arel[parent_column].eq(parent_id_was)
|
@@ -371,47 +374,61 @@ module ActsAsOrderedTree
|
|
371
374
|
arel[parent_column].eq(parent_id)
|
372
375
|
)
|
373
376
|
|
374
|
-
binds = {:
|
375
|
-
:parent_id_was => parent_id_was,
|
377
|
+
binds = {:parent_id_was => parent_id_was,
|
376
378
|
:parent_id => parent_id,
|
377
379
|
:position_was => position_was,
|
378
380
|
:position => position,
|
379
381
|
:depth => depth}
|
380
382
|
|
381
|
-
|
383
|
+
update_changed_attributes! conditions, assignments, binds
|
382
384
|
end
|
383
385
|
|
384
386
|
# Internal
|
385
387
|
def reorder!(parent_id, position_was, position)
|
386
|
-
assignments =
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
388
|
+
assignments = [
|
389
|
+
if position_was
|
390
|
+
<<-SQL
|
391
|
+
#{position_column} = CASE
|
392
|
+
WHEN #{position_column} = :position_was
|
393
|
+
THEN :position
|
394
|
+
WHEN #{position_column} <= :position AND #{position_column} > :position_was AND :position > :position_was
|
395
|
+
THEN #{position_column} - 1
|
396
|
+
WHEN #{position_column} >= :position AND #{position_column} < :position_was AND :position < :position_was
|
397
|
+
THEN #{position_column} + 1
|
398
|
+
ELSE #{position_column}
|
399
|
+
END
|
400
|
+
SQL
|
401
|
+
else
|
402
|
+
<<-SQL
|
403
|
+
#{position_column} = CASE
|
404
|
+
WHEN #{position_column} > :position
|
405
|
+
THEN #{position_column} + 1
|
406
|
+
WHEN #{position_column} IS NULL
|
407
|
+
THEN :position
|
408
|
+
ELSE #{position_column}
|
409
|
+
END
|
410
|
+
SQL
|
411
|
+
end
|
412
|
+
]
|
409
413
|
|
410
414
|
conditions = arel[parent_column].eq(parent_id)
|
411
|
-
|
412
415
|
binds = {:position_was => position_was, :position => position}
|
413
416
|
|
414
|
-
|
417
|
+
update_changed_attributes! conditions, assignments, binds
|
418
|
+
end
|
419
|
+
|
420
|
+
def update_changed_attributes!(scope_conditions, assignments, binds)
|
421
|
+
# add assignments for externally changed attributes
|
422
|
+
internal_attributes = [parent_column.to_s, position_column.to_s, depth_column.to_s, self.class.primary_key]
|
423
|
+
external_changed_attrs = changed - internal_attributes
|
424
|
+
unless external_changed_attrs.empty?
|
425
|
+
external_changed_attrs.each do |attr|
|
426
|
+
assignments << "#{attr} = CASE WHEN #{self.class.primary_key} = :id THEN :#{attr} ELSE #{attr} END"
|
427
|
+
binds[attr.to_sym] = self[attr]
|
428
|
+
end
|
429
|
+
end
|
430
|
+
|
431
|
+
ordered_tree_scope.where(scope_conditions).update_all([assignments.compact.join(', '), {:id => id}.merge(binds)])
|
415
432
|
end
|
416
433
|
|
417
434
|
# recursively load descendants
|
@@ -448,7 +465,7 @@ module ActsAsOrderedTree
|
|
448
465
|
|
449
466
|
# Used in built-in around_move routine
|
450
467
|
def update_counter_cache #:nodoc:
|
451
|
-
parent_id_was =
|
468
|
+
parent_id_was = send "#{parent_column}_was"
|
452
469
|
|
453
470
|
yield
|
454
471
|
|
@@ -729,6 +729,32 @@ describe ActsAsOrderedTree, :transactional do
|
|
729
729
|
child_3.move_to_child_of child_1
|
730
730
|
record.reload.depth.should eq 3
|
731
731
|
end
|
732
|
+
|
733
|
+
context "DefaultWithCallbacks" do
|
734
|
+
let!(:cb_root_1) { create :default_with_callbacks, :name => 'root_1' }
|
735
|
+
let!(:cb_root_2) { create :default_with_callbacks, :name => 'root_2' }
|
736
|
+
let!(:cb_child_1) { create :default_with_callbacks, :name => 'child_1', :parent => cb_root_1 }
|
737
|
+
let!(:cb_child_2) { create :default_with_callbacks, :name => 'child_2', :parent => cb_root_1 }
|
738
|
+
|
739
|
+
specify "new parent_id should be available in before_move" do
|
740
|
+
cb_root_2.stub(:before_move) { cb_root_2.parent_id.should eq cb_root_1.id }
|
741
|
+
cb_root_2.move_to_left_of cb_child_1
|
742
|
+
end
|
743
|
+
|
744
|
+
specify "new position should be available in before_reorder" do
|
745
|
+
cb_child_2.stub(:before_reorder) { cb_child_2.position.should eq 1 }
|
746
|
+
cb_child_2.move_to_left_of cb_child_1
|
747
|
+
end
|
748
|
+
end
|
749
|
+
|
750
|
+
end
|
751
|
+
|
752
|
+
context "changed attributes" do
|
753
|
+
specify "changed attributes should be saved" do
|
754
|
+
child_2.name = 'name100'
|
755
|
+
child_2.move_to_left_of child_1
|
756
|
+
child_2.reload.name.should eq 'name100'
|
757
|
+
end
|
732
758
|
end
|
733
759
|
|
734
760
|
end
|
@@ -7,14 +7,11 @@ if ActiveRecord::VERSION::STRING >= "3.1" && ENV['DB'] != 'sqlite3'
|
|
7
7
|
module Concurrency
|
8
8
|
# run block in its own thread, create +size+ threads
|
9
9
|
def pool(size)
|
10
|
-
|
11
|
-
|
12
|
-
yield x
|
10
|
+
size.times.map { |x|
|
11
|
+
Thread.new do
|
12
|
+
ActiveRecord::Base.connection_pool.with_connection { yield x }
|
13
13
|
end
|
14
|
-
|
15
|
-
threads = size.times.map { |x| Thread.new { body.call(x) } }
|
16
|
-
|
17
|
-
threads.each(&:join)
|
14
|
+
}.each(&:join)
|
18
15
|
end
|
19
16
|
end
|
20
17
|
include Concurrency
|
data/spec/spec_helper.rb
CHANGED
data/spec/support/factories.rb
CHANGED
@@ -7,6 +7,10 @@ FactoryGirl.define do
|
|
7
7
|
sequence(:name) { |n| "category #{n}" }
|
8
8
|
end
|
9
9
|
|
10
|
+
factory :default_with_callbacks do
|
11
|
+
sequence(:name) { |n| "category #{n}" }
|
12
|
+
end
|
13
|
+
|
10
14
|
factory :scoped do
|
11
15
|
sequence(:scope_type) { |n| "type_#{n}" }
|
12
16
|
sequence(:name) { |n| "category #{n}" }
|
data/spec/support/models.rb
CHANGED
@@ -16,6 +16,22 @@ class DefaultWithCounterCache < ActiveRecord::Base
|
|
16
16
|
acts_as_ordered_tree :counter_cache => :categories_count
|
17
17
|
end
|
18
18
|
|
19
|
+
class DefaultWithCallbacks < ActiveRecord::Base
|
20
|
+
self.table_name = "categories"
|
21
|
+
|
22
|
+
acts_as_ordered_tree
|
23
|
+
|
24
|
+
after_move :after_move
|
25
|
+
before_move :before_move
|
26
|
+
after_reorder :after_reorder
|
27
|
+
before_reorder :before_reorder
|
28
|
+
|
29
|
+
def after_move; end
|
30
|
+
def before_move; end
|
31
|
+
def after_reorder; end
|
32
|
+
def before_reorder; end
|
33
|
+
end
|
34
|
+
|
19
35
|
class Scoped < ActiveRecord::Base
|
20
36
|
self.table_name = "scoped"
|
21
37
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: acts_as_ordered_tree
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2012-
|
13
|
+
date: 2012-10-29 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activerecord
|
@@ -164,7 +164,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
164
164
|
version: '0'
|
165
165
|
segments:
|
166
166
|
- 0
|
167
|
-
hash:
|
167
|
+
hash: 1615306957006760355
|
168
168
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
169
169
|
none: false
|
170
170
|
requirements:
|
@@ -173,7 +173,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
173
173
|
version: '0'
|
174
174
|
segments:
|
175
175
|
- 0
|
176
|
-
hash:
|
176
|
+
hash: 1615306957006760355
|
177
177
|
requirements: []
|
178
178
|
rubyforge_project: acts_as_ordered_tree
|
179
179
|
rubygems_version: 1.8.24
|