DanaDanger-hyrarchy 0.1 → 0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/hyrarchy/awesome_nested_set_compatibility.rb +19 -1
- data/lib/hyrarchy/collection_proxy.rb +10 -0
- data/lib/hyrarchy.rb +36 -45
- metadata +2 -2
@@ -60,7 +60,6 @@ module Hyrarchy
|
|
60
60
|
return true if (valid? rescue false)
|
61
61
|
|
62
62
|
update_all("lft = id, rgt = id, lft_numer = id, lft_denom = id")
|
63
|
-
reset_all_free_child_paths
|
64
63
|
paths_by_id = {}
|
65
64
|
order_by = columns_hash['created_at'] ? :created_at : :id
|
66
65
|
|
@@ -210,6 +209,25 @@ module Hyrarchy
|
|
210
209
|
end
|
211
210
|
rows.length
|
212
211
|
end
|
212
|
+
end,
|
213
|
+
# Associations don't normally have an optimized index method, but
|
214
|
+
# this one does. :)
|
215
|
+
:index => Proc.new do |obj|
|
216
|
+
rows = self.class.connection.select_all("
|
217
|
+
SELECT id, lft_numer, lft_denom
|
218
|
+
FROM #{self.class.quoted_table_name}
|
219
|
+
WHERE #{descendants.conditions}
|
220
|
+
ORDER BY rgt DESC, lft")
|
221
|
+
r = encoded_path.next_farey_fraction
|
222
|
+
rows.delete_if do |row|
|
223
|
+
p = Hyrarchy::EncodedPath(
|
224
|
+
row['lft_numer'].to_i,
|
225
|
+
row['lft_denom'].to_i)
|
226
|
+
row.delete('lft_numer')
|
227
|
+
row.delete('lft_denom')
|
228
|
+
p < encoded_path || p >= r
|
229
|
+
end
|
230
|
+
rows.index({'id' => obj.id.to_s})
|
213
231
|
end
|
214
232
|
)
|
215
233
|
end
|
@@ -7,6 +7,7 @@ module Hyrarchy
|
|
7
7
|
def initialize(owner, name, options = {})
|
8
8
|
@after = options.delete(:after)
|
9
9
|
@count = options.delete(:count)
|
10
|
+
@index = options.delete(:index)
|
10
11
|
reflection = ActiveRecord::Base.create_reflection(
|
11
12
|
:has_many, name, options.merge(:class_name => owner.class.to_s), owner.class)
|
12
13
|
super(owner, reflection)
|
@@ -52,6 +53,15 @@ module Hyrarchy
|
|
52
53
|
end
|
53
54
|
end
|
54
55
|
|
56
|
+
# Overrides index to run the association's +index+ procedure.
|
57
|
+
def index(obj)
|
58
|
+
if @index && !loaded?
|
59
|
+
@index.call(obj)
|
60
|
+
else
|
61
|
+
super
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
55
65
|
protected
|
56
66
|
|
57
67
|
# Overrides find_target to run the association's +after+ procedure on the
|
data/lib/hyrarchy.rb
CHANGED
@@ -80,7 +80,7 @@ module Hyrarchy
|
|
80
80
|
|
81
81
|
before_save :set_encoded_paths
|
82
82
|
before_save :set_parent_id
|
83
|
-
|
83
|
+
after_save :update_descendant_paths
|
84
84
|
|
85
85
|
named_scope :roots,
|
86
86
|
:conditions => { :parent_id => nil },
|
@@ -96,41 +96,17 @@ module Hyrarchy
|
|
96
96
|
|
97
97
|
private
|
98
98
|
|
99
|
-
# Returns an array of unused child paths beneath +parent_path+.
|
100
|
-
def free_child_paths(parent_path)
|
101
|
-
@@free_child_paths ||= {}
|
102
|
-
@@free_child_paths[parent_path] ||= []
|
103
|
-
end
|
104
|
-
|
105
|
-
# Stores +path+ in the arrays of free child paths.
|
106
|
-
def child_path_is_free(path)
|
107
|
-
parent_path = path.parent(false)
|
108
|
-
free_child_paths(parent_path) << path
|
109
|
-
free_child_paths(parent_path).sort!
|
110
|
-
end
|
111
|
-
|
112
|
-
# Removes all paths from the array of free child paths for +parent_path+.
|
113
|
-
def reset_free_child_paths(parent_path)
|
114
|
-
free_child_paths(parent_path).clear
|
115
|
-
end
|
116
|
-
|
117
|
-
# Removes all paths from the array of free child paths.
|
118
|
-
def reset_all_free_child_paths
|
119
|
-
@@free_child_paths = {}
|
120
|
-
end
|
121
|
-
|
122
99
|
# Finds the first unused child path beneath +parent_path+.
|
123
100
|
def next_child_encoded_path(parent_path)
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
p = parent_path.mediant(p)
|
101
|
+
if parent_path == Hyrarchy::EncodedPath::ROOT
|
102
|
+
if sibling = roots.last
|
103
|
+
sibling.send(:encoded_path).next_sibling
|
128
104
|
else
|
129
|
-
|
130
|
-
child_path_is_free(parent_path.mediant(p))
|
131
|
-
end
|
132
|
-
return p
|
105
|
+
Hyrarchy::EncodedPath::ROOT.first_child
|
133
106
|
end
|
107
|
+
else
|
108
|
+
node = find_by_encoded_path(parent_path)
|
109
|
+
node ? node.send(:next_child_encoded_path) : parent_path.first_child
|
134
110
|
end
|
135
111
|
end
|
136
112
|
|
@@ -202,7 +178,7 @@ module Hyrarchy
|
|
202
178
|
paths.collect {|p| "(lft_numer = ? AND lft_denom = ?)"}.join(" OR "),
|
203
179
|
*(paths.collect {|p| [p.numerator, p.denominator]}.flatten)
|
204
180
|
],
|
205
|
-
:order => 'rgt
|
181
|
+
:order => 'rgt, lft DESC'
|
206
182
|
)
|
207
183
|
end
|
208
184
|
|
@@ -249,6 +225,7 @@ module Hyrarchy
|
|
249
225
|
self.lft = nil
|
250
226
|
self.rgt = nil
|
251
227
|
else
|
228
|
+
@path_has_changed = true
|
252
229
|
self.lft_numer = r.numerator
|
253
230
|
self.lft_denom = r.denominator
|
254
231
|
self.lft = r.to_f
|
@@ -268,12 +245,22 @@ module Hyrarchy
|
|
268
245
|
@cached ||= {}
|
269
246
|
end
|
270
247
|
|
248
|
+
# Returns the first unused child path under this node.
|
249
|
+
def next_child_encoded_path
|
250
|
+
return nil unless encoded_path
|
251
|
+
if children.empty?
|
252
|
+
encoded_path.first_child
|
253
|
+
else
|
254
|
+
children.last.send(:encoded_path).next_sibling
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
271
258
|
private
|
272
259
|
|
273
260
|
# before_save callback to ensure that this node's encoded path is a child
|
274
|
-
# of its parent
|
275
|
-
# has moved.
|
261
|
+
# of its parent.
|
276
262
|
def set_encoded_paths # :nodoc:
|
263
|
+
@path_has_changed = false if @path_has_changed.nil?
|
277
264
|
p = nil
|
278
265
|
self.lft_numer = self.lft_denom = nil if @make_root
|
279
266
|
|
@@ -287,13 +274,8 @@ module Hyrarchy
|
|
287
274
|
|
288
275
|
if p
|
289
276
|
new_path = self.class.send(:next_child_encoded_path, p)
|
290
|
-
if encoded_path != new_path
|
291
|
-
self.class.send(:reset_free_child_paths, encoded_path)
|
277
|
+
if @path_has_changed = (encoded_path != new_path)
|
292
278
|
self.encoded_path = new_path
|
293
|
-
children.each do |c|
|
294
|
-
c.parent = self
|
295
|
-
c.save!
|
296
|
-
end
|
297
279
|
end
|
298
280
|
end
|
299
281
|
|
@@ -308,10 +290,19 @@ module Hyrarchy
|
|
308
290
|
true
|
309
291
|
end
|
310
292
|
|
311
|
-
#
|
312
|
-
#
|
313
|
-
def
|
314
|
-
|
293
|
+
# after_save callback to ensure that this node's descendants are updated if
|
294
|
+
# this node has moved.
|
295
|
+
def update_descendant_paths
|
296
|
+
return true unless @path_has_changed
|
297
|
+
|
298
|
+
child_path = encoded_path.first_child
|
299
|
+
children.each do |c|
|
300
|
+
c.encoded_path = child_path
|
301
|
+
c.save!
|
302
|
+
child_path = child_path.next_sibling
|
303
|
+
end
|
304
|
+
|
305
|
+
true
|
315
306
|
end
|
316
307
|
end
|
317
308
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: DanaDanger-hyrarchy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: "0.
|
4
|
+
version: "0.2"
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dana Danger
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-12-
|
12
|
+
date: 2008-12-22 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|