simple_nested_set 0.0.24 → 0.0.25
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/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
|