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