fertile_forest 0.0.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE +22 -0
- data/README.rdoc +3 -0
- data/config/routes.rb +2 -0
- data/lib/fertile_forest/engine.rb +13 -0
- data/lib/fertile_forest/modules/calculators.rb +231 -0
- data/lib/fertile_forest/modules/configs.rb +96 -0
- data/lib/fertile_forest/modules/entities.rb +233 -0
- data/lib/fertile_forest/modules/finders.rb +736 -0
- data/lib/fertile_forest/modules/reconstructers.rb +843 -0
- data/lib/fertile_forest/modules/states.rb +271 -0
- data/lib/fertile_forest/modules/utilities.rb +188 -0
- data/lib/fertile_forest/saplings.rb +330 -0
- data/lib/fertile_forest/version.rb +1 -1
- data/lib/fertile_forest.rb +7 -3
- data/lib/tasks/fertile_forest_tasks.rake +4 -0
- metadata +19 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e7fb8b7fe6a221ca6fa537152448626b03bfa453
|
4
|
+
data.tar.gz: 55da6e1a5fcb682e8e0a1cc2239df52e32bfb53f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3600025777793045fc0faaa17c1b3a150dc91bb11432589fd199b64b12f62ae4295960a6e2d5b5aa088880e6528dfb5cf7853800138ab9dc109637bf477653bf
|
7
|
+
data.tar.gz: 9eaf893afade620cbdae109ce6144b36fac204dcae85d2a18fb87b555784543c6a5b7bbb14f4e4a7a4b19deff3c8ca562174b5fb977cf7c849056569b614d623
|
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015 Stew Eucen
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
22
|
+
|
data/README.rdoc
ADDED
data/config/routes.rb
ADDED
@@ -0,0 +1,231 @@
|
|
1
|
+
#
|
2
|
+
# Calcurators methods
|
3
|
+
# Fertile Forest for Ruby: The new model for storing hierarchical data in a database.
|
4
|
+
#
|
5
|
+
# @author StewEucen
|
6
|
+
# @copyright Copyright (c) 2015 Stew Eucen (http://lab.kochlein.com)
|
7
|
+
# @license http://www.opensource.org/licenses/mit-license.php MIT License
|
8
|
+
#
|
9
|
+
# @link http://lab.kochlein.com/FertileForest
|
10
|
+
# @since File available since Release 1.0.0
|
11
|
+
# @version 1.0.0
|
12
|
+
#
|
13
|
+
module StewEucen
|
14
|
+
# Name space of Stew Eucen's Acts
|
15
|
+
module Acts
|
16
|
+
# Name space of Fertile Forest
|
17
|
+
module FertileForest
|
18
|
+
# Name space of class methods for Fertile Forest
|
19
|
+
module Table
|
20
|
+
# This module is for extending into derived class by ActiveRecord.<br>
|
21
|
+
# The caption contains "Instance Methods",
|
22
|
+
# but it means "Class Methods" of each derived class.
|
23
|
+
# @private
|
24
|
+
module Calculators
|
25
|
+
|
26
|
+
def fill_required_columns_to_append!(node)
|
27
|
+
# calculate depth and queue for appending.
|
28
|
+
# If no interval, try to scoot over queue.
|
29
|
+
if node.ff_base_id.to_i <= 0
|
30
|
+
fill_info = ff_calc_required_columns_for_appending_as_root(node)
|
31
|
+
else
|
32
|
+
fill_info = ff_calc_required_columns_for_appending_as_internal(node)
|
33
|
+
end
|
34
|
+
|
35
|
+
# When fail to calc, can not save.
|
36
|
+
# no need to set error message here.
|
37
|
+
return false if fill_info.blank?
|
38
|
+
|
39
|
+
# not need to set ff_grove, because posted node has it already.
|
40
|
+
node.ff_queue = fill_info[:ff_queue]
|
41
|
+
node.ff_depth = fill_info[:ff_depth]
|
42
|
+
|
43
|
+
true
|
44
|
+
end
|
45
|
+
|
46
|
+
def ff_parse_kinship(node)
|
47
|
+
ff_kinship_key = node.ff_kinship
|
48
|
+
if /true|false/i.match(ff_kinship_key)
|
49
|
+
ff_kinship_key === 'true'
|
50
|
+
else
|
51
|
+
ff_kinship_key.to_i
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
#
|
56
|
+
# Calculate depth and queue as root node to append.
|
57
|
+
# @return [Hash] Calculated queue and depth.
|
58
|
+
# @return [false] Can not calculate.
|
59
|
+
#
|
60
|
+
def ff_calc_required_columns_for_appending_as_root(node)
|
61
|
+
# can be null=zero
|
62
|
+
posted_grove = node.ff_grove.to_i
|
63
|
+
|
64
|
+
# When append as root, need to post ff_grove.
|
65
|
+
if has_grove? && posted_grove <= 0
|
66
|
+
# TODO: set error message 'append_empty_column'
|
67
|
+
return false
|
68
|
+
end
|
69
|
+
|
70
|
+
# depth is fixed value
|
71
|
+
fill_info = {ff_depth: ROOT_DEPTH}
|
72
|
+
|
73
|
+
####################################################################
|
74
|
+
#
|
75
|
+
# calculate queue
|
76
|
+
#
|
77
|
+
|
78
|
+
# get max queue in grove
|
79
|
+
last_queue = ff_get_last_queue(posted_grove) # can be nil
|
80
|
+
|
81
|
+
if last_queue.nil?
|
82
|
+
append_queue = 0
|
83
|
+
elsif QUEUE_MAX_VALUE <= last_queue
|
84
|
+
# Try to scoot over pre-nodes.
|
85
|
+
evenize_res = ff_evenize(posted_grove, nil, nil, 1) # 1: append node count
|
86
|
+
|
87
|
+
# When fail to evenize, filled all id.
|
88
|
+
if evenize_res.blank?
|
89
|
+
# TODO: set error append.canNotScootsOver'
|
90
|
+
return false
|
91
|
+
end
|
92
|
+
|
93
|
+
append_queue = evenize_res[SPROUT_VACANT_QUEUE_KEY]
|
94
|
+
elsif QUEUE_MAX_VALUE - last_queue < QUEUE_DEFAULT_INTERVAL
|
95
|
+
append_queue = QUEUE_MAX_VALUE
|
96
|
+
else
|
97
|
+
append_queue = last_queue + QUEUE_DEFAULT_INTERVAL
|
98
|
+
end
|
99
|
+
|
100
|
+
# return value
|
101
|
+
fill_info.merge({ff_queue: append_queue})
|
102
|
+
end
|
103
|
+
|
104
|
+
#
|
105
|
+
# Calculate depth and queue as internal node to append.
|
106
|
+
# (1) has space before base-node, calc median queue.
|
107
|
+
# (2) When no space befre base node, try to evenize.
|
108
|
+
# (3) can not evenize, can not append.
|
109
|
+
# @return [Hash] Calculated queue and depth.
|
110
|
+
# @return [false] Can not calculate.
|
111
|
+
#
|
112
|
+
def ff_calc_required_columns_for_appending_as_internal(node)
|
113
|
+
base_id = node.ff_base_id.to_i
|
114
|
+
grove_id = node.ff_grove.to_i
|
115
|
+
|
116
|
+
# get base node by ff_base_id
|
117
|
+
# use ff_grove for find, because grove means USER_ID
|
118
|
+
base_node = ff_required_columns_scope()
|
119
|
+
.ff_usual_conditions_scope(grove_id)
|
120
|
+
.where(id: base_id)
|
121
|
+
.first
|
122
|
+
|
123
|
+
# When has ff_base_id and the node is nothing, fail to append.
|
124
|
+
if base_node.blank?
|
125
|
+
# TODO: set errors append.baseNodeIsNull
|
126
|
+
return false
|
127
|
+
end
|
128
|
+
|
129
|
+
kinship = ff_parse_kinship(node)
|
130
|
+
is_sibling = ff_is_bool(kinship)
|
131
|
+
|
132
|
+
# depth is fixed value
|
133
|
+
fill_info = {ff_depth: base_node.ff_depth.to_i + (is_sibling ? 0 : 1)}
|
134
|
+
|
135
|
+
# pick up node for wedged node to scoot over. (can be null)
|
136
|
+
wedged_node = ff_get_wedged_node(base_node, kinship)
|
137
|
+
|
138
|
+
# When wedged node is nothing, it means last queue.
|
139
|
+
# In the case, calc appending queue is "lastQueue + INTERVAL"
|
140
|
+
|
141
|
+
if wedged_node.blank?
|
142
|
+
last_queue = ff_get_last_queue(grove_id, 0)
|
143
|
+
if last_queue < QUEUE_MAX_VALUE
|
144
|
+
if QUEUE_DEFAULT_INTERVAL <= QUEUE_MAX_VALUE - last_queue
|
145
|
+
calc_queue = last_queue + QUEUE_DEFAULT_INTERVAL
|
146
|
+
else
|
147
|
+
calc_queue = QUEUE_MAX_VALUE
|
148
|
+
end
|
149
|
+
|
150
|
+
return fill_info.merge({ff_queue: calc_queue})
|
151
|
+
end
|
152
|
+
else
|
153
|
+
#
|
154
|
+
# When got wedged node, calc median queue.
|
155
|
+
# (1) get previous node of the wedge node.
|
156
|
+
# (2) calc median queue.
|
157
|
+
#
|
158
|
+
append_queue = ff_calc_median_queue(wedged_node)
|
159
|
+
|
160
|
+
return fill_info.merge({ff_queue: append_queue}) \
|
161
|
+
if append_queue.present?
|
162
|
+
end
|
163
|
+
|
164
|
+
# When no space before wedged node, try to scoot over.
|
165
|
+
append_queue = ff_evenize_for_appending(base_node, wedged_node)
|
166
|
+
|
167
|
+
return fill_info.merge({ff_queue: append_queue}) \
|
168
|
+
if append_queue.present?
|
169
|
+
|
170
|
+
# TODO: set error message append.canNotScootsOver
|
171
|
+
false
|
172
|
+
end
|
173
|
+
|
174
|
+
def ff_calc_median_queue(wedged_node)
|
175
|
+
tail_node = ff_get_previous_node(wedged_node)
|
176
|
+
|
177
|
+
# tail_node never be null, because parent-node exists.
|
178
|
+
return nil if tail_node.blank?
|
179
|
+
|
180
|
+
tail_queue = tail_node.ff_queue
|
181
|
+
wedged_queue = wedged_node.ff_queue
|
182
|
+
|
183
|
+
return nil if wedged_queue - tail_queue <= 1
|
184
|
+
|
185
|
+
# not need to use (int)
|
186
|
+
(tail_queue + wedged_queue) / 2
|
187
|
+
end
|
188
|
+
|
189
|
+
def ff_evenize_for_appending(base_node, wedged_node)
|
190
|
+
append_node_count = 1
|
191
|
+
|
192
|
+
grove_id = base_node.ff_grove
|
193
|
+
base_queue = base_node.blank? ? nil : base_node .ff_queue
|
194
|
+
wedged_queue = wedged_node.blank? ? nil : wedged_node.ff_queue
|
195
|
+
|
196
|
+
# try to evenize all pre-nodes from this base node.
|
197
|
+
evenize_res = ff_evenize(grove_id, base_queue, wedged_queue, append_node_count)
|
198
|
+
return evenize_res[SPROUT_VACANT_QUEUE_KEY] if evenize_res.present?
|
199
|
+
|
200
|
+
# try to evenize all pre-nodes from this root node.
|
201
|
+
# {
|
202
|
+
# $rootNode = $this->root($baseNode);
|
203
|
+
# $evenizeRes = $this->_evenize($grove, $rootNode, $wedgedQueue, $appendNodeCount);
|
204
|
+
# if (!empty($evenizeRes)) {
|
205
|
+
# return $evenizeRes[self::SPROUT_VACANT_QUEUE_KEY];
|
206
|
+
# }
|
207
|
+
# }
|
208
|
+
|
209
|
+
# try to evenize all pre-nodes.
|
210
|
+
evenize_res = ff_evenize(grove_id, nil, wedged_queue, append_node_count)
|
211
|
+
return evenize_res[SPROUT_VACANT_QUEUE_KEY] if evenize_res.present?
|
212
|
+
|
213
|
+
# try to evenize all post-nodes.
|
214
|
+
evenize_res = ff_evenize(grove_id, wedged_queue, nil, append_node_count, true)
|
215
|
+
return evenize_res[SPROUT_VACANT_QUEUE_KEY] if evenize_res.present?
|
216
|
+
|
217
|
+
# can not evenize.
|
218
|
+
false
|
219
|
+
end
|
220
|
+
|
221
|
+
protected :ff_parse_kinship,
|
222
|
+
:ff_calc_required_columns_for_appending_as_root,
|
223
|
+
:ff_calc_required_columns_for_appending_as_internal,
|
224
|
+
:ff_calc_median_queue,
|
225
|
+
:ff_evenize_for_appending
|
226
|
+
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
#
|
2
|
+
# Configs methods
|
3
|
+
# Fertile Forest for Ruby: The new model for storing hierarchical data in a database.
|
4
|
+
#
|
5
|
+
# @author StewEucen
|
6
|
+
# @copyright Copyright (c) 2015 Stew Eucen (http://lab.kochlein.com)
|
7
|
+
# @license http://www.opensource.org/licenses/mit-license.php MIT License
|
8
|
+
#
|
9
|
+
# @link http://lab.kochlein.com/FertileForest
|
10
|
+
# @since File available since Release 1.0.0
|
11
|
+
# @version 1.0.0
|
12
|
+
#
|
13
|
+
module StewEucen
|
14
|
+
# Name space of Stew Eucen's Acts
|
15
|
+
module Acts
|
16
|
+
# Name space of Fertile Forest
|
17
|
+
module FertileForest
|
18
|
+
# Name space of class methods for Fertile Forest
|
19
|
+
module Table
|
20
|
+
# This module is for extending into derived class by ActiveRecord.<br>
|
21
|
+
# The caption contains "Instance Methods",
|
22
|
+
# but it means "Class Methods" of each derived class.
|
23
|
+
module Configs
|
24
|
+
|
25
|
+
#
|
26
|
+
# Exists grove field in table?
|
27
|
+
#
|
28
|
+
# @author StewEucen
|
29
|
+
# @return [Boolean] true: has grove column.
|
30
|
+
# @return [Boolean] false: no grove column.
|
31
|
+
# @since Release 1.0.0
|
32
|
+
#
|
33
|
+
def has_grove?
|
34
|
+
ff_has_column? :ff_grove
|
35
|
+
end
|
36
|
+
|
37
|
+
#
|
38
|
+
# Exists soft-delete field in table?
|
39
|
+
#
|
40
|
+
# @author StewEucen
|
41
|
+
# @return [Boolean] true: has soft-delete column.
|
42
|
+
# @return [Boolean] false: no soft-delete column.
|
43
|
+
# @since Release 1.0.0
|
44
|
+
#
|
45
|
+
def has_soft_delete?
|
46
|
+
ff_has_column? :ff_soft_delete
|
47
|
+
end
|
48
|
+
|
49
|
+
#
|
50
|
+
# Is enable to use soft-delete by grove field?
|
51
|
+
#
|
52
|
+
# @author StewEucen
|
53
|
+
# @return [Boolean] true: enable.
|
54
|
+
# @return [Boolean] false: disable.
|
55
|
+
# @since Release 1.0.0
|
56
|
+
#
|
57
|
+
def enable_grove_delete?
|
58
|
+
has_grove? \
|
59
|
+
&& !has_soft_delete? \
|
60
|
+
&& ff_options[:enable_grove_delete]
|
61
|
+
# Need back slashes for this writing.
|
62
|
+
end
|
63
|
+
|
64
|
+
#
|
65
|
+
# Exists field in table?
|
66
|
+
#
|
67
|
+
# @author StewEucen
|
68
|
+
# @param column [Symbol] Column symbol to check.
|
69
|
+
# @return [Boolean] true: has specified column.
|
70
|
+
# @return [Boolean] false: no specified column.
|
71
|
+
# @since Release 1.0.0
|
72
|
+
#
|
73
|
+
def ff_has_column?(column)
|
74
|
+
key = column.to_s
|
75
|
+
attribute_aliases[key] || column_names.include?(key)
|
76
|
+
end
|
77
|
+
|
78
|
+
#
|
79
|
+
# Recommended queue interval for appending node.
|
80
|
+
# Can overwrite [queue interval] at setup()/initialize().
|
81
|
+
#
|
82
|
+
# @author StewEucen
|
83
|
+
# @return [Integer] Default queue interval.
|
84
|
+
# @since Release 1.0.0
|
85
|
+
#
|
86
|
+
def ff_get_query_interval
|
87
|
+
QUEUE_DEFAULT_INTERVAL
|
88
|
+
end
|
89
|
+
|
90
|
+
protected :ff_has_column?,
|
91
|
+
:ff_get_query_interval
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,233 @@
|
|
1
|
+
#
|
2
|
+
# Fertile Forest for Ruby
|
3
|
+
# The new model for storing hierarchical data in a database.
|
4
|
+
#
|
5
|
+
# @author StewEucen
|
6
|
+
# @copyright Copyright (c) 2015 Stew Eucen (http://lab.kochlein.com)
|
7
|
+
# @license http://www.opensource.org/licenses/mit-license.php MIT License
|
8
|
+
#
|
9
|
+
# @link http://lab.kochlein.com/FertileForest
|
10
|
+
# @since File available since Release 1.0.0
|
11
|
+
# @version 1.0.0
|
12
|
+
#
|
13
|
+
module StewEucen
|
14
|
+
# Name space of Stew Eucen's Acts
|
15
|
+
module Acts
|
16
|
+
# Name space of Fertile Forest
|
17
|
+
module FertileForest
|
18
|
+
#
|
19
|
+
# Instance methods to include into derived class by ActiveRecord.
|
20
|
+
#
|
21
|
+
# @author StewEucen
|
22
|
+
# @example Include into ActiveRecord class.
|
23
|
+
# ActiveRecord::Base.send :include, StewEucen::Acts::FertileForest::Entity
|
24
|
+
# @since Release 1.0.0
|
25
|
+
#
|
26
|
+
module Entity
|
27
|
+
#
|
28
|
+
# Before save listener (must be an instance methoed).
|
29
|
+
# Transparently manages setting the required fields for FertileForestBehavior
|
30
|
+
# if the parent field is included in the parameters to be saved.
|
31
|
+
#
|
32
|
+
# @return boolean true:Continue to save./false:Abort to save.
|
33
|
+
#
|
34
|
+
def ff_before_save
|
35
|
+
# when not new record, to update.
|
36
|
+
# no need to set ff_columns (id, grove, queue, depth)
|
37
|
+
return true unless new_record?
|
38
|
+
|
39
|
+
if self.class.has_grove?
|
40
|
+
posted_grove = self.ff_grove
|
41
|
+
if posted_grove.blank?
|
42
|
+
# TODO: set_error
|
43
|
+
return false
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# return value
|
48
|
+
self.class.fill_required_columns_to_append!(self)
|
49
|
+
end
|
50
|
+
|
51
|
+
def ff_before_create
|
52
|
+
end
|
53
|
+
|
54
|
+
def ff_after_save
|
55
|
+
end
|
56
|
+
|
57
|
+
def ff_before_destroy
|
58
|
+
end
|
59
|
+
|
60
|
+
protected :ff_before_save,
|
61
|
+
:ff_before_create,
|
62
|
+
:ff_after_save,
|
63
|
+
:ff_before_destroy
|
64
|
+
|
65
|
+
########################################################################
|
66
|
+
|
67
|
+
def ff_reset_values
|
68
|
+
{
|
69
|
+
parent: {0 => nil},
|
70
|
+
children: {},
|
71
|
+
}
|
72
|
+
end
|
73
|
+
|
74
|
+
def ff_get_options
|
75
|
+
@fertile_forest ||= ff_reset_values
|
76
|
+
end
|
77
|
+
|
78
|
+
def nest_unset_parent
|
79
|
+
ff_get_options[:parent] = {0 => nil}
|
80
|
+
end
|
81
|
+
|
82
|
+
def nest_unset_children(id = nil)
|
83
|
+
if id.blank?
|
84
|
+
ff_get_options[:children] = {}
|
85
|
+
else
|
86
|
+
ff_get_options[:children][id] = nil
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
##
|
91
|
+
#
|
92
|
+
# accessors
|
93
|
+
#
|
94
|
+
#
|
95
|
+
########################################################################
|
96
|
+
|
97
|
+
def nest_parent_node
|
98
|
+
ff_get_options[:parent].values.first
|
99
|
+
end
|
100
|
+
|
101
|
+
def nest_child_nodes
|
102
|
+
ff_get_options[:children]
|
103
|
+
end
|
104
|
+
|
105
|
+
def nest_parent_id
|
106
|
+
ff_get_options[:parent].keys.first
|
107
|
+
end
|
108
|
+
|
109
|
+
def nest_child_ids
|
110
|
+
ff_get_options[:children].keys
|
111
|
+
end
|
112
|
+
|
113
|
+
alias nest_parent nest_parent_node
|
114
|
+
alias nest_genitor nest_parent_node
|
115
|
+
alias nest_children nest_child_nodes
|
116
|
+
|
117
|
+
########################################################################
|
118
|
+
|
119
|
+
def nest_set_parent_id(aim_id)
|
120
|
+
ff_get_options[:parent] = {aim_id => nil} # always overwrite
|
121
|
+
end
|
122
|
+
|
123
|
+
def nest_set_child_id(aim_id)
|
124
|
+
ff_get_options[:children][aim_id] = nil
|
125
|
+
end
|
126
|
+
|
127
|
+
########################################################################
|
128
|
+
|
129
|
+
def nest_set_parent_node(aim_id, node)
|
130
|
+
ff_get_options[:parent] = {aim_id => node} \
|
131
|
+
if aim_id.present? && node.present?
|
132
|
+
end
|
133
|
+
|
134
|
+
def nest_set_child_node(aim_id, node)
|
135
|
+
ff_get_options[:children][aim_id] = node \
|
136
|
+
if aim_id.present? && node.present?
|
137
|
+
end
|
138
|
+
|
139
|
+
########################################################################
|
140
|
+
|
141
|
+
def nest_leaf?
|
142
|
+
ff_get_options[:children].blank?
|
143
|
+
end
|
144
|
+
|
145
|
+
def nest_parent?
|
146
|
+
!nest_leaf?
|
147
|
+
end
|
148
|
+
|
149
|
+
########################################################################
|
150
|
+
|
151
|
+
def trunk(range = ANCESTOR_ALL, columns = nil)
|
152
|
+
self.class.trunk(self, range, columns)
|
153
|
+
end
|
154
|
+
|
155
|
+
def ancestors(columns = nil)
|
156
|
+
self.class.ancestors(self, columns)
|
157
|
+
end
|
158
|
+
|
159
|
+
def genitor(columns = nil)
|
160
|
+
self.class.genitor(self, columns)
|
161
|
+
end
|
162
|
+
|
163
|
+
def root(columns = nil)
|
164
|
+
self.class.root(self, columns)
|
165
|
+
end
|
166
|
+
|
167
|
+
def grandparent(columns = nil)
|
168
|
+
self.class.grandparent(self, columns)
|
169
|
+
end
|
170
|
+
|
171
|
+
def subtree(range = DESCENDANTS_ALL, with_top = true, columns = nil)
|
172
|
+
self.class.subtree(self, range, with_top, columns)
|
173
|
+
end
|
174
|
+
|
175
|
+
def descendants(columns = nil)
|
176
|
+
self.class.descendants(self, columns)
|
177
|
+
end
|
178
|
+
|
179
|
+
def children(columns = nil)
|
180
|
+
self.class.children(self, columns)
|
181
|
+
end
|
182
|
+
|
183
|
+
def nth_child(nth = 0, columns = nil)
|
184
|
+
self.class.nth_child(self, nth, columns)
|
185
|
+
end
|
186
|
+
|
187
|
+
def grandchildren(columns = nil)
|
188
|
+
self.class.grandchildren(self, columns)
|
189
|
+
end
|
190
|
+
|
191
|
+
def siblings(columns = nil)
|
192
|
+
self.class.siblings(self, columns)
|
193
|
+
end
|
194
|
+
|
195
|
+
def nth_sibling(nth = 0, columns = nil)
|
196
|
+
self.class.nth_sibling(self, nth, columns)
|
197
|
+
end
|
198
|
+
|
199
|
+
def elder_sibling(columns = nil)
|
200
|
+
self.class.elder_sibling(self, columns)
|
201
|
+
end
|
202
|
+
|
203
|
+
def younger_sibling(columns = nil)
|
204
|
+
self.class.younger_sibling(self, columns)
|
205
|
+
end
|
206
|
+
|
207
|
+
def offset_sibling(offset, columns = nil)
|
208
|
+
self.class.offset_sibling(self, offset, columns)
|
209
|
+
end
|
210
|
+
|
211
|
+
def leaves(columns = nil)
|
212
|
+
self.class.leaves(self, columns)
|
213
|
+
end
|
214
|
+
|
215
|
+
def internals(columns = nil)
|
216
|
+
self.class.internals(self, columns)
|
217
|
+
end
|
218
|
+
|
219
|
+
def height
|
220
|
+
self.class.height(self)
|
221
|
+
end
|
222
|
+
|
223
|
+
def size
|
224
|
+
self.class.size(self)
|
225
|
+
end
|
226
|
+
|
227
|
+
protected :ff_reset_values,
|
228
|
+
:ff_get_options
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
end
|
233
|
+
end
|