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.
@@ -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
- ].compact.join(', ')
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 = {:id => id,
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
- ordered_tree_scope.where(conditions).update_all([assignments, binds])
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 = if position_was
387
- <<-SQL
388
- #{position_column} = CASE
389
- WHEN #{position_column} = :position_was
390
- THEN :position
391
- WHEN #{position_column} <= :position AND #{position_column} > :position_was AND :position > :position_was
392
- THEN #{position_column} - 1
393
- WHEN #{position_column} >= :position AND #{position_column} < :position_was AND :position < :position_was
394
- THEN #{position_column} + 1
395
- ELSE #{position_column}
396
- END
397
- SQL
398
- else
399
- <<-SQL
400
- #{position_column} = CASE
401
- WHEN #{position_column} > :position
402
- THEN #{position_column} + 1
403
- WHEN #{position_column} IS NULL
404
- THEN :position
405
- ELSE #{position_column}
406
- END
407
- SQL
408
- end
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
- ordered_tree_scope.where(conditions).update_all([assignments, binds])
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 = self[parent_column]
468
+ parent_id_was = send "#{parent_column}_was"
452
469
 
453
470
  yield
454
471
 
@@ -1,3 +1,3 @@
1
1
  module ActsAsOrderedTree
2
- VERSION = "1.1.1"
2
+ VERSION = "1.1.2"
3
3
  end
@@ -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
- body = proc do |x|
11
- ActiveRecord::Base.connection_pool.with_connection do
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
- end
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
@@ -50,6 +50,7 @@ RSpec.configure do |config|
50
50
  ensure
51
51
  Default.delete_all
52
52
  DefaultWithCounterCache.delete_all
53
+ DefaultWithCallbacks.delete_all
53
54
  Scoped.delete_all
54
55
  end
55
56
  end
@@ -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}" }
@@ -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.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-09-14 00:00:00.000000000 Z
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: 2475944794341416152
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: 2475944794341416152
176
+ hash: 1615306957006760355
177
177
  requirements: []
178
178
  rubyforge_project: acts_as_ordered_tree
179
179
  rubygems_version: 1.8.24