acts_as_ordered_tree 1.3.1 → 2.0.0.beta3
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 +4 -4
- data/lib/acts_as_ordered_tree.rb +22 -100
- data/lib/acts_as_ordered_tree/adapters.rb +17 -0
- data/lib/acts_as_ordered_tree/adapters/abstract.rb +23 -0
- data/lib/acts_as_ordered_tree/adapters/postgresql.rb +150 -0
- data/lib/acts_as_ordered_tree/adapters/recursive.rb +157 -0
- data/lib/acts_as_ordered_tree/compatibility.rb +22 -0
- data/lib/acts_as_ordered_tree/compatibility/active_record/association_scope.rb +9 -0
- data/lib/acts_as_ordered_tree/compatibility/active_record/default_scoped.rb +19 -0
- data/lib/acts_as_ordered_tree/compatibility/active_record/null_relation.rb +71 -0
- data/lib/acts_as_ordered_tree/compatibility/features.rb +153 -0
- data/lib/acts_as_ordered_tree/deprecate.rb +24 -0
- data/lib/acts_as_ordered_tree/hooks.rb +38 -0
- data/lib/acts_as_ordered_tree/hooks/update.rb +86 -0
- data/lib/acts_as_ordered_tree/instance_methods.rb +92 -453
- data/lib/acts_as_ordered_tree/iterators/arranger.rb +35 -0
- data/lib/acts_as_ordered_tree/iterators/level_calculator.rb +52 -0
- data/lib/acts_as_ordered_tree/iterators/orphans_pruner.rb +58 -0
- data/lib/acts_as_ordered_tree/node.rb +78 -0
- data/lib/acts_as_ordered_tree/node/attributes.rb +48 -0
- data/lib/acts_as_ordered_tree/node/movement.rb +62 -0
- data/lib/acts_as_ordered_tree/node/movements.rb +111 -0
- data/lib/acts_as_ordered_tree/node/predicates.rb +98 -0
- data/lib/acts_as_ordered_tree/node/reloading.rb +49 -0
- data/lib/acts_as_ordered_tree/node/siblings.rb +139 -0
- data/lib/acts_as_ordered_tree/node/traversals.rb +53 -0
- data/lib/acts_as_ordered_tree/persevering_transaction.rb +93 -0
- data/lib/acts_as_ordered_tree/position.rb +143 -0
- data/lib/acts_as_ordered_tree/relation/arrangeable.rb +33 -0
- data/lib/acts_as_ordered_tree/relation/iterable.rb +41 -0
- data/lib/acts_as_ordered_tree/relation/preloaded.rb +46 -11
- data/lib/acts_as_ordered_tree/transaction/base.rb +57 -0
- data/lib/acts_as_ordered_tree/transaction/callbacks.rb +67 -0
- data/lib/acts_as_ordered_tree/transaction/create.rb +68 -0
- data/lib/acts_as_ordered_tree/transaction/destroy.rb +34 -0
- data/lib/acts_as_ordered_tree/transaction/dsl.rb +214 -0
- data/lib/acts_as_ordered_tree/transaction/factory.rb +67 -0
- data/lib/acts_as_ordered_tree/transaction/move.rb +70 -0
- data/lib/acts_as_ordered_tree/transaction/passthrough.rb +12 -0
- data/lib/acts_as_ordered_tree/transaction/reorder.rb +42 -0
- data/lib/acts_as_ordered_tree/transaction/save.rb +64 -0
- data/lib/acts_as_ordered_tree/transaction/update.rb +78 -0
- data/lib/acts_as_ordered_tree/tree.rb +148 -0
- data/lib/acts_as_ordered_tree/tree/association.rb +20 -0
- data/lib/acts_as_ordered_tree/tree/callbacks.rb +57 -0
- data/lib/acts_as_ordered_tree/tree/children_association.rb +120 -0
- data/lib/acts_as_ordered_tree/tree/columns.rb +102 -0
- data/lib/acts_as_ordered_tree/tree/deprecated_columns_accessors.rb +24 -0
- data/lib/acts_as_ordered_tree/tree/parent_association.rb +31 -0
- data/lib/acts_as_ordered_tree/tree/perseverance.rb +19 -0
- data/lib/acts_as_ordered_tree/tree/scopes.rb +56 -0
- data/lib/acts_as_ordered_tree/validators.rb +1 -1
- data/lib/acts_as_ordered_tree/version.rb +1 -1
- data/spec/acts_as_ordered_tree_spec.rb +80 -909
- data/spec/adapters/postgresql_spec.rb +14 -0
- data/spec/adapters/recursive_spec.rb +12 -0
- data/spec/adapters/shared.rb +272 -0
- data/spec/callbacks_spec.rb +177 -0
- data/spec/counter_cache_spec.rb +31 -0
- data/spec/create_spec.rb +110 -0
- data/spec/destroy_spec.rb +57 -0
- data/spec/inheritance_spec.rb +176 -0
- data/spec/move_spec.rb +94 -0
- data/spec/node/movements/concurrent_movements_spec.rb +354 -0
- data/spec/node/movements/move_higher_spec.rb +46 -0
- data/spec/node/movements/move_lower_spec.rb +46 -0
- data/spec/node/movements/move_to_child_of_spec.rb +147 -0
- data/spec/node/movements/move_to_child_with_index_spec.rb +124 -0
- data/spec/node/movements/move_to_child_with_position_spec.rb +85 -0
- data/spec/node/movements/move_to_left_of_spec.rb +120 -0
- data/spec/node/movements/move_to_right_of_spec.rb +120 -0
- data/spec/node/movements/move_to_root_spec.rb +67 -0
- data/spec/node/predicates_spec.rb +211 -0
- data/spec/node/reloading_spec.rb +42 -0
- data/spec/node/siblings_spec.rb +193 -0
- data/spec/node/traversals_spec.rb +71 -0
- data/spec/persevering_transaction_spec.rb +98 -0
- data/spec/relation/arrangeable_spec.rb +88 -0
- data/spec/relation/iterable_spec.rb +104 -0
- data/spec/relation/preloaded_spec.rb +57 -0
- data/spec/reorder_spec.rb +83 -0
- data/spec/spec_helper.rb +30 -38
- data/spec/support/db/boot.rb +22 -0
- data/spec/{db → support/db}/config.travis.yml +2 -0
- data/spec/{db → support/db}/config.yml +1 -0
- data/spec/{db → support/db}/schema.rb +9 -0
- data/spec/support/factories.rb +2 -2
- data/spec/support/matchers.rb +67 -58
- data/spec/support/models.rb +6 -14
- data/spec/support/tree_factory.rb +315 -0
- data/spec/tree/children_association_spec.rb +72 -0
- data/spec/tree/columns_spec.rb +65 -0
- data/spec/tree/scopes_spec.rb +39 -0
- metadata +161 -43
- data/lib/acts_as_ordered_tree/adapters/postgresql_adapter.rb +0 -104
- data/lib/acts_as_ordered_tree/arrangeable.rb +0 -80
- data/lib/acts_as_ordered_tree/class_methods.rb +0 -72
- data/lib/acts_as_ordered_tree/relation/base.rb +0 -26
- data/lib/acts_as_ordered_tree/tenacious_transaction.rb +0 -30
- data/spec/concurrency_support_spec.rb +0 -156
@@ -0,0 +1,20 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module ActsAsOrderedTree
|
4
|
+
class Tree
|
5
|
+
class Association
|
6
|
+
attr_reader :tree
|
7
|
+
|
8
|
+
delegate :klass, :to => :tree
|
9
|
+
|
10
|
+
def initialize(tree)
|
11
|
+
@tree = tree
|
12
|
+
end
|
13
|
+
|
14
|
+
protected
|
15
|
+
def class_name
|
16
|
+
"::#{tree.base_class.name}"
|
17
|
+
end
|
18
|
+
end # class Association
|
19
|
+
end # class Tree
|
20
|
+
end # module ActsAsOrderedTree
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'active_support/core_ext/hash/slice'
|
4
|
+
|
5
|
+
module ActsAsOrderedTree
|
6
|
+
class Tree
|
7
|
+
# Tree callbacks storage
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# MyModel.ordered_tree.callbacks.before_add(parent, child)
|
11
|
+
#
|
12
|
+
# @api private
|
13
|
+
class Callbacks
|
14
|
+
VALID_KEYS = :before_add,
|
15
|
+
:after_add,
|
16
|
+
:before_remove,
|
17
|
+
:after_remove
|
18
|
+
|
19
|
+
def initialize(klass, options)
|
20
|
+
@klass = klass
|
21
|
+
@callbacks = {}
|
22
|
+
|
23
|
+
options.slice(*VALID_KEYS).each do |k, v|
|
24
|
+
@callbacks[k] = v if v
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# generate accessors and predicates
|
29
|
+
VALID_KEYS.each do |method|
|
30
|
+
define_method(method) do |parent, record| # def before_add(parent, record)
|
31
|
+
run_callbacks(method, parent, record)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
def run_callbacks(method, parent, record)
|
37
|
+
callback = callback_for(method)
|
38
|
+
|
39
|
+
case callback
|
40
|
+
when Symbol
|
41
|
+
parent.send(callback, record)
|
42
|
+
when Proc
|
43
|
+
callback.call(parent, record)
|
44
|
+
when nil, false
|
45
|
+
# do nothing
|
46
|
+
else
|
47
|
+
# parent.before_add(record)
|
48
|
+
callback.send(method, parent, record)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def callback_for(method)
|
53
|
+
@callbacks[method]
|
54
|
+
end
|
55
|
+
end # class Callbacks
|
56
|
+
end # class Tree
|
57
|
+
end # module ActsAsOrderedTree
|
@@ -0,0 +1,120 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'acts_as_ordered_tree/compatibility'
|
4
|
+
require 'acts_as_ordered_tree/tree/association'
|
5
|
+
require 'acts_as_ordered_tree/relation/iterable'
|
6
|
+
|
7
|
+
module ActsAsOrderedTree
|
8
|
+
class Tree
|
9
|
+
# @api private
|
10
|
+
class ChildrenAssociation < Association
|
11
|
+
# CounterCache extensions will allow to use cached value
|
12
|
+
#
|
13
|
+
# @api private
|
14
|
+
module CounterCache
|
15
|
+
def size
|
16
|
+
ordered_tree_node.parent_id_changed? ? super : ordered_tree_node.counter_cache
|
17
|
+
end
|
18
|
+
|
19
|
+
def empty?
|
20
|
+
size == 0
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
def ordered_tree_node
|
25
|
+
@association.owner.ordered_tree_node
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Builds association object
|
30
|
+
def build
|
31
|
+
Compatibility.version '< 4.0.0' do
|
32
|
+
opts = options.merge(:conditions => conditions, :order => order)
|
33
|
+
|
34
|
+
klass.has_many(:children, opts)
|
35
|
+
end
|
36
|
+
|
37
|
+
Compatibility.version '>= 4.0.0' do
|
38
|
+
klass.has_many(:children, scope, options)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
def options
|
44
|
+
Hash[
|
45
|
+
:class_name => class_name,
|
46
|
+
:foreign_key => tree.columns.parent,
|
47
|
+
:inverse_of => inverse_of,
|
48
|
+
:dependent => :destroy,
|
49
|
+
:extend => [extension, Relation::Iterable].compact
|
50
|
+
]
|
51
|
+
end
|
52
|
+
|
53
|
+
def inverse_of
|
54
|
+
:parent unless tree.options[:polymorphic]
|
55
|
+
end
|
56
|
+
|
57
|
+
# rails 4.x scope for has_many association
|
58
|
+
def scope
|
59
|
+
assoc_scope = method(:association_scope)
|
60
|
+
join_scope = method(:join_association_scope)
|
61
|
+
|
62
|
+
->(join_or_parent) {
|
63
|
+
if join_or_parent.is_a?(ActiveRecord::Associations::JoinDependency::JoinAssociation)
|
64
|
+
join_scope[join_or_parent]
|
65
|
+
elsif join_or_parent.is_a?(ActiveRecord::Base)
|
66
|
+
assoc_scope[join_or_parent]
|
67
|
+
else
|
68
|
+
where(nil)
|
69
|
+
end.extending(Relation::Iterable)
|
70
|
+
}
|
71
|
+
end
|
72
|
+
|
73
|
+
# Rails 3.x :conditions options for has_many association
|
74
|
+
def conditions
|
75
|
+
return nil unless tree.columns.scope?
|
76
|
+
|
77
|
+
assoc_scope = method(:association_scope)
|
78
|
+
join_scope = method(:join_association_scope)
|
79
|
+
|
80
|
+
Proc.new do |join_association|
|
81
|
+
conditions = if join_association.is_a?(ActiveRecord::Associations::JoinDependency::JoinAssociation)
|
82
|
+
join_scope[join_association]
|
83
|
+
elsif self.is_a?(ActiveRecord::Base)
|
84
|
+
assoc_scope[self]
|
85
|
+
else
|
86
|
+
where(nil)
|
87
|
+
end.where_values.reduce(:and)
|
88
|
+
|
89
|
+
conditions.try(:to_sql)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def order
|
94
|
+
tree.columns.position
|
95
|
+
end
|
96
|
+
|
97
|
+
def extension
|
98
|
+
if tree.columns.counter_cache?
|
99
|
+
CounterCache
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def join_association_scope(join_association)
|
104
|
+
parent = join_association.respond_to?(:parent) ?
|
105
|
+
join_association.parent.table :
|
106
|
+
join_association.base_klass.arel_table
|
107
|
+
|
108
|
+
child = join_association.table
|
109
|
+
|
110
|
+
conditions = tree.columns.scope.map { |column| parent[column].eq child[column] }.reduce(:and)
|
111
|
+
|
112
|
+
klass.unscoped.where(conditions)
|
113
|
+
end
|
114
|
+
|
115
|
+
def association_scope(owner)
|
116
|
+
owner.ordered_tree_node.scope.order(tree.columns.position)
|
117
|
+
end
|
118
|
+
end # class ChildrenAssociation
|
119
|
+
end # class Tree
|
120
|
+
end # module ActsAsOrderedTree
|
@@ -0,0 +1,102 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module ActsAsOrderedTree
|
4
|
+
class Tree
|
5
|
+
# Ordered tree columns store
|
6
|
+
#
|
7
|
+
# @example
|
8
|
+
# MyModel.tree.columns.parent # => "parent_id"
|
9
|
+
# MyModel.tree.columns.counter_cache # => nil
|
10
|
+
# MyModel.tree.columns.counter_cache? # => false
|
11
|
+
class Columns
|
12
|
+
# This error is raised when unknown column given in :scope option
|
13
|
+
UnknownColumn = Class.new(StandardError)
|
14
|
+
|
15
|
+
# @api private
|
16
|
+
def self.column_accessor(*names)
|
17
|
+
names.each do |name|
|
18
|
+
define_method "#{name}=" do |value|
|
19
|
+
@columns[name] = value.to_s if column_exists?(value)
|
20
|
+
end
|
21
|
+
private "#{name}=".to_sym
|
22
|
+
|
23
|
+
define_method "#{name}?" do
|
24
|
+
@columns[name].present?
|
25
|
+
end
|
26
|
+
|
27
|
+
define_method name do
|
28
|
+
@columns[name]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# @!method parent
|
34
|
+
# @!method parent?
|
35
|
+
# @!method parent=(value)
|
36
|
+
# @!method position
|
37
|
+
# @!method position?
|
38
|
+
# @!method position=(value)
|
39
|
+
# @!method depth
|
40
|
+
# @!method depth?
|
41
|
+
# @!method depth=(value)
|
42
|
+
# @!method counter_cache
|
43
|
+
# @!method counter_cache?
|
44
|
+
# @!method counter_cache=(value)
|
45
|
+
# @!method scope
|
46
|
+
# @!method scope?
|
47
|
+
column_accessor :parent,
|
48
|
+
:position,
|
49
|
+
:depth,
|
50
|
+
:counter_cache,
|
51
|
+
:scope
|
52
|
+
|
53
|
+
def initialize(klass, options = {})
|
54
|
+
@klass = klass
|
55
|
+
@columns = { :id => id }
|
56
|
+
|
57
|
+
self.parent = options[:parent_column]
|
58
|
+
self.position = options[:position_column]
|
59
|
+
self.depth = options[:depth_column]
|
60
|
+
self.counter_cache = counter_cache_name(options[:counter_cache])
|
61
|
+
self.scope = options[:scope]
|
62
|
+
end
|
63
|
+
|
64
|
+
def [](name)
|
65
|
+
@columns[name]
|
66
|
+
end
|
67
|
+
|
68
|
+
def id
|
69
|
+
@klass.primary_key
|
70
|
+
end
|
71
|
+
|
72
|
+
# Returns array of columns names associated with ordered tree structure
|
73
|
+
def to_a
|
74
|
+
@columns.values.flatten.compact
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
undef_method :scope=
|
79
|
+
def scope=(value)
|
80
|
+
columns = Array.wrap(value)
|
81
|
+
|
82
|
+
unknown = columns.reject { |name| column_exists?(name) }
|
83
|
+
|
84
|
+
raise UnknownColumn, "Unknown column#{'s' if unknown.size > 1} passed to :scope option: #{unknown.join(', ')}" if unknown.any?
|
85
|
+
|
86
|
+
@columns[:scope] = columns.map(&:to_s)
|
87
|
+
end
|
88
|
+
|
89
|
+
def counter_cache_name(value)
|
90
|
+
if value == true
|
91
|
+
"#{@klass.name.demodulize.underscore.pluralize}_count"
|
92
|
+
else
|
93
|
+
value
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def column_exists?(name)
|
98
|
+
name.present? && @klass.columns_hash.include?(name.to_s)
|
99
|
+
end
|
100
|
+
end # class Columns
|
101
|
+
end # class Tree
|
102
|
+
end # module ActsAsOrderedTree
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module ActsAsOrderedTree
|
2
|
+
class Tree
|
3
|
+
# @deprecated Use `ordered_tree.columns` object
|
4
|
+
module DeprecatedColumnsAccessors
|
5
|
+
class << self
|
6
|
+
# @api private
|
7
|
+
def deprecated_method(method, delegate)
|
8
|
+
define_method(method) do
|
9
|
+
ActiveSupport::Deprecation.warn("#{name}.#{method} is deprecated in favor of #{name}.ordered_tree.columns.#{delegate}", caller(1))
|
10
|
+
|
11
|
+
ordered_tree.columns.send(delegate)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
private :deprecated_method
|
15
|
+
end
|
16
|
+
|
17
|
+
deprecated_method :parent_column, :parent
|
18
|
+
deprecated_method :position_column, :position
|
19
|
+
deprecated_method :depth_column, :depth
|
20
|
+
deprecated_method :children_counter_cache_column, :counter_cache
|
21
|
+
deprecated_method :scope_column_name, :scope
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'acts_as_ordered_tree/tree/association'
|
4
|
+
|
5
|
+
module ActsAsOrderedTree
|
6
|
+
class Tree
|
7
|
+
class ParentAssociation < Association
|
8
|
+
# create parent association
|
9
|
+
#
|
10
|
+
# we cannot use native :counter_cache callbacks because they suck! :(
|
11
|
+
# they act like this:
|
12
|
+
# node.parent = new_parent # and here counters are updated, outside of transaction!
|
13
|
+
def build
|
14
|
+
klass.belongs_to(:parent, options)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
def options
|
19
|
+
Hash[
|
20
|
+
:class_name => class_name,
|
21
|
+
:foreign_key => tree.columns.parent,
|
22
|
+
:inverse_of => inverse_of
|
23
|
+
]
|
24
|
+
end
|
25
|
+
|
26
|
+
def inverse_of
|
27
|
+
:children unless tree.options[:polymorphic]
|
28
|
+
end
|
29
|
+
end # class ParentAssociation
|
30
|
+
end # class Tree
|
31
|
+
end # module ActsAsOrderedTree
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'acts_as_ordered_tree/persevering_transaction'
|
4
|
+
|
5
|
+
module ActsAsOrderedTree
|
6
|
+
class Tree
|
7
|
+
# This module contains overridden :with_transaction_returning_status method
|
8
|
+
# which wraps itself into PerseveringTransaction.
|
9
|
+
#
|
10
|
+
# This module is mixed in into Class after Class.acts_as_ordered_tree invocation.
|
11
|
+
#
|
12
|
+
# @api private
|
13
|
+
module Perseverance
|
14
|
+
def with_transaction_returning_status
|
15
|
+
PerseveringTransaction.new(self.class.connection).start { super }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module ActsAsOrderedTree
|
4
|
+
class Tree
|
5
|
+
module Scopes
|
6
|
+
# Returns nodes ordered by their position.
|
7
|
+
#
|
8
|
+
# @return [ActiveRecord::Relation]
|
9
|
+
def preorder
|
10
|
+
order arel_table[ordered_tree.columns.position].asc
|
11
|
+
end
|
12
|
+
|
13
|
+
# Returns all nodes that don't have parent.
|
14
|
+
#
|
15
|
+
# @return [ActiveRecord::Relation]
|
16
|
+
def roots
|
17
|
+
preorder.where arel_table[ordered_tree.columns.parent].eq nil
|
18
|
+
end
|
19
|
+
|
20
|
+
# Returns all nodes that do not have any children. May be quite inefficient.
|
21
|
+
#
|
22
|
+
# @return [ActiveRecord::Relation]
|
23
|
+
def root
|
24
|
+
roots.first
|
25
|
+
end
|
26
|
+
|
27
|
+
# Returns all nodes that do not have any children. May be quite inefficient.
|
28
|
+
#
|
29
|
+
# @return [ActiveRecord::Relation]
|
30
|
+
def leaves
|
31
|
+
if ordered_tree.columns.counter_cache?
|
32
|
+
leaves_with_counter_cache
|
33
|
+
else
|
34
|
+
leaves_without_counter_cache
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
def leaves_without_counter_cache
|
40
|
+
aliaz = Arel::Nodes::TableAlias.new(arel_table, 't')
|
41
|
+
|
42
|
+
subquery = unscoped.select('1').
|
43
|
+
from(aliaz).
|
44
|
+
where(aliaz[ordered_tree.columns.parent].eq(arel_table[primary_key])).
|
45
|
+
limit(1).
|
46
|
+
reorder(nil)
|
47
|
+
|
48
|
+
where "NOT EXISTS (#{subquery.to_sql})"
|
49
|
+
end
|
50
|
+
|
51
|
+
def leaves_with_counter_cache
|
52
|
+
where arel_table[ordered_tree.columns.counter_cache].eq 0
|
53
|
+
end
|
54
|
+
end # module Scopes
|
55
|
+
end # class Tree
|
56
|
+
end # module ActsAsOrderedTree
|
@@ -8,7 +8,7 @@ module ActsAsOrderedTree
|
|
8
8
|
|
9
9
|
class ScopeValidator < ActiveModel::Validator
|
10
10
|
def validate(record)
|
11
|
-
record.errors.add(:parent, :scope) unless record.same_scope?(record.parent)
|
11
|
+
record.errors.add(:parent, :scope) unless record.ordered_tree_node.same_scope?(record.parent)
|
12
12
|
end
|
13
13
|
end
|
14
14
|
end
|