simple_nested_set 0.0.24 → 0.0.25
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/simple_nested_set/class_methods.rb +25 -4
- data/lib/simple_nested_set/instance_methods.rb +6 -6
- data/lib/simple_nested_set/nested_set.rb +15 -3
- data/lib/simple_nested_set/rebuild/from_parents.rb +56 -0
- data/lib/simple_nested_set/version.rb +1 -1
- data/lib/simple_nested_set.rb +1 -0
- metadata +10 -7
@@ -37,12 +37,20 @@ module SimpleNestedSet
|
|
37
37
|
where(:parent_id => parent_id).order(:lft)
|
38
38
|
end
|
39
39
|
|
40
|
-
def with_ancestors(lft, rgt)
|
41
|
-
|
40
|
+
def with_ancestors(lft, rgt, opts = {})
|
41
|
+
if opts.fetch(:include_self, false)
|
42
|
+
where(arel_table[:lft].lteq(lft).and(arel_table[:rgt].gteq(rgt))).order(:lft)
|
43
|
+
else
|
44
|
+
where(arel_table[:lft].lt(lft).and(arel_table[:rgt].gt(rgt))).order(:lft)
|
45
|
+
end
|
42
46
|
end
|
43
47
|
|
44
|
-
def with_descendants(lft, rgt)
|
45
|
-
|
48
|
+
def with_descendants(lft, rgt, opts = {})
|
49
|
+
if opts.fetch(:include_self, false)
|
50
|
+
where(arel_table[:lft].gteq(lft).and(arel_table[:rgt].lteq(rgt))).order(:lft)
|
51
|
+
else
|
52
|
+
where(arel_table[:lft].gt(lft).and(arel_table[:rgt].lt(rgt))).order(:lft)
|
53
|
+
end
|
46
54
|
end
|
47
55
|
|
48
56
|
def with_left_sibling(lft)
|
@@ -57,5 +65,18 @@ module SimpleNestedSet
|
|
57
65
|
# where("#{arel_table[:lft].to_sql} = #{arel_table[:rgt].to_sql} - 1").order(:lft)
|
58
66
|
where("#{arel_table.name}.lft = #{arel_table.name}.rgt - 1").order(:lft)
|
59
67
|
end
|
68
|
+
|
69
|
+
def nested_set_transaction(sort_order = :id)
|
70
|
+
begin
|
71
|
+
nested_set_class.move_after_save = false
|
72
|
+
self.transaction do
|
73
|
+
yield self
|
74
|
+
# nested_set_class.new(self).rebuild_by_parents!
|
75
|
+
Rebuild::FromParents.new.run(self, sort_order)
|
76
|
+
end
|
77
|
+
ensure
|
78
|
+
nested_set_class.move_after_save = true
|
79
|
+
end
|
80
|
+
end
|
60
81
|
end
|
61
82
|
end
|
@@ -63,13 +63,13 @@ module SimpleNestedSet
|
|
63
63
|
end
|
64
64
|
|
65
65
|
# Returns an array of all parents
|
66
|
-
def ancestors
|
67
|
-
nested_set.with_ancestors(lft, rgt)
|
66
|
+
def ancestors(opts = {})
|
67
|
+
nested_set.with_ancestors(lft, rgt, opts)
|
68
68
|
end
|
69
69
|
|
70
70
|
# Returns the array of all parents and self
|
71
71
|
def self_and_ancestors
|
72
|
-
ancestors
|
72
|
+
ancestors(:include_self => true)
|
73
73
|
end
|
74
74
|
|
75
75
|
# Returns true if this is a descendent of the given node
|
@@ -83,13 +83,13 @@ module SimpleNestedSet
|
|
83
83
|
end
|
84
84
|
|
85
85
|
# Returns a set of all of its children and nested children.
|
86
|
-
def descendants
|
87
|
-
|
86
|
+
def descendants(opts = {})
|
87
|
+
nested_set.with_descendants(lft, rgt, opts)
|
88
88
|
end
|
89
89
|
|
90
90
|
# Returns a set of itself and all of its nested children.
|
91
91
|
def self_and_descendants
|
92
|
-
|
92
|
+
descendants(:include_self => true)
|
93
93
|
end
|
94
94
|
|
95
95
|
# Returns the number of descendants
|
@@ -2,12 +2,13 @@ module SimpleNestedSet
|
|
2
2
|
class NestedSet < ActiveRecord::Relation
|
3
3
|
include SqlAbstraction
|
4
4
|
|
5
|
-
class_inheritable_accessor :node_class, :scope_names
|
5
|
+
class_inheritable_accessor :node_class, :scope_names, :move_after_save
|
6
6
|
|
7
7
|
class << self
|
8
8
|
def build_class(model, scopes)
|
9
9
|
model.const_get(:NestedSet) rescue model.const_set(:NestedSet, Class.new(NestedSet)).tap do |node_class|
|
10
10
|
node_class.node_class = model
|
11
|
+
node_class.move_after_save = true
|
11
12
|
node_class.scope_names = Array(scopes).map { |s| s.to_s =~ /_id$/ ? s.to_sym : :"#{s}_id" }
|
12
13
|
end
|
13
14
|
end
|
@@ -41,8 +42,15 @@ module SimpleNestedSet
|
|
41
42
|
def save!
|
42
43
|
attributes = node.instance_variable_get(:@_nested_set_attributes)
|
43
44
|
node.instance_variable_set(:@_nested_set_attributes, nil)
|
44
|
-
|
45
|
-
|
45
|
+
|
46
|
+
if self.class.move_after_save
|
47
|
+
move_by_attributes(attributes) unless attributes.blank?
|
48
|
+
denormalize!
|
49
|
+
elsif attributes
|
50
|
+
attributes.each do |key, value|
|
51
|
+
node.update_attribute(key, value)
|
52
|
+
end
|
53
|
+
end
|
46
54
|
end
|
47
55
|
|
48
56
|
# FIXME we don't always want to call this on after_save, do we? it's only relevant when
|
@@ -121,6 +129,10 @@ module SimpleNestedSet
|
|
121
129
|
Rebuild::FromPaths.new.run(self)
|
122
130
|
end
|
123
131
|
|
132
|
+
def rebuild_from_parents!(sort_order = nil)
|
133
|
+
Rebuild::FromParents.new.run(self, sort_order)
|
134
|
+
end
|
135
|
+
|
124
136
|
def denormalize_level_query
|
125
137
|
aliaz = arel_table.as(:l)
|
126
138
|
query = aliaz.project(aliaz[:id].count).
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module SimpleNestedSet
|
2
|
+
module Rebuild
|
3
|
+
class FromParents
|
4
|
+
attr_writer :num
|
5
|
+
|
6
|
+
def num
|
7
|
+
@num ||= 0
|
8
|
+
end
|
9
|
+
|
10
|
+
def run(nested_set, sort_order = nil)
|
11
|
+
order_columns = ([:parent_id] + Array[sort_order]).compact
|
12
|
+
|
13
|
+
nodes = if nested_set.respond_to?(:except)
|
14
|
+
nested_set.except(:order).order(order_columns)
|
15
|
+
else
|
16
|
+
nested_set.reorder(order_columns)
|
17
|
+
end.to_a
|
18
|
+
|
19
|
+
renumber(nodes.dup)
|
20
|
+
nodes.each(&:save)
|
21
|
+
end
|
22
|
+
|
23
|
+
def renumber(nodes)
|
24
|
+
until nodes.empty?
|
25
|
+
node = nodes.shift
|
26
|
+
node.lft = self.num += 1
|
27
|
+
num = renumber(extract_children(node, nodes))
|
28
|
+
node.rgt = self.num += 1
|
29
|
+
end
|
30
|
+
num
|
31
|
+
end
|
32
|
+
|
33
|
+
def extract_children(node, nodes)
|
34
|
+
children = nodes.select { |child| child?(node, child) }
|
35
|
+
nodes.replace(nodes - children)
|
36
|
+
children
|
37
|
+
end
|
38
|
+
|
39
|
+
def child?(node, child)
|
40
|
+
if child.root?
|
41
|
+
false
|
42
|
+
elsif direct_child?(node, child)
|
43
|
+
true
|
44
|
+
else
|
45
|
+
# recurse to find indirect children,
|
46
|
+
# i.e. the child is one of the grandchildren of the node
|
47
|
+
child?(node, child.parent)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def direct_child? node, child
|
52
|
+
child.parent_id == node.id
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/lib/simple_nested_set.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: simple_nested_set
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 45
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 25
|
10
|
+
version: 0.0.25
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Sven Fuchs
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-11-
|
18
|
+
date: 2010-11-29 00:00:00 +01:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -82,12 +82,14 @@ dependencies:
|
|
82
82
|
requirement: &id005 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
|
-
- - "
|
85
|
+
- - "="
|
86
86
|
- !ruby/object:Gem::Version
|
87
|
-
hash:
|
87
|
+
hash: 15
|
88
88
|
segments:
|
89
89
|
- 0
|
90
|
-
|
90
|
+
- 5
|
91
|
+
- 2
|
92
|
+
version: 0.5.2
|
91
93
|
type: :development
|
92
94
|
version_requirements: *id005
|
93
95
|
- !ruby/object:Gem::Dependency
|
@@ -122,6 +124,7 @@ files:
|
|
122
124
|
- lib/simple_nested_set/move/to_target.rb
|
123
125
|
- lib/simple_nested_set/nested_set.rb
|
124
126
|
- lib/simple_nested_set/patches/arel_table_initialization.rb
|
127
|
+
- lib/simple_nested_set/rebuild/from_parents.rb
|
125
128
|
- lib/simple_nested_set/rebuild/from_paths.rb
|
126
129
|
- lib/simple_nested_set/sql_abstraction.rb
|
127
130
|
- lib/simple_nested_set/version.rb
|