DanaDanger-hyrarchy 0.2 → 0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -260,13 +260,28 @@ module Hyrarchy
260
260
  def same_scope?(other)
261
261
  true
262
262
  end
263
-
263
+
264
+ # Returns the sibling before this node. If this node is its parent's
265
+ # first child, returns nil.
264
266
  def left_sibling # :nodoc:
265
- raise NotImplementedError, "awesome_nested_set's left_sibling method isn't implemented in this version of Hyrarchy"
267
+ path = send(:encoded_path)
268
+ return nil if path == path.parent.first_child
269
+ sibling_path = path.previous_sibling
270
+ until self.class.exists?(:lft_numer => sibling_path.numerator, :lft_denom => sibling_path.denominator)
271
+ sibling_path = sibling_path.previous_sibling
272
+ end
273
+ self.class.send(:find_by_encoded_path, sibling_path)
266
274
  end
267
275
 
268
- def right_sibling # :nodoc:
269
- raise NotImplementedError, "awesome_nested_set's right_sibling method isn't implemented in this version of Hyrarchy"
276
+ # Returns the sibling after this node. If this node is its parent's last
277
+ # child, returns nil.
278
+ def right_sibling
279
+ return nil if self == parent.children.last
280
+ sibling_path = send(:encoded_path).next_sibling
281
+ until self.class.exists?(:lft_numer => sibling_path.numerator, :lft_denom => sibling_path.denominator)
282
+ sibling_path = sibling_path.next_sibling
283
+ end
284
+ self.class.send(:find_by_encoded_path, sibling_path)
270
285
  end
271
286
 
272
287
  def move_left # :nodoc:
@@ -276,13 +291,58 @@ module Hyrarchy
276
291
  def move_right # :nodoc:
277
292
  raise NotImplementedError, "awesome_nested_set's move_right method isn't implemented in this version of Hyrarchy"
278
293
  end
279
-
280
- def move_to_left_of(other) # :nodoc:
281
- raise NotImplementedError, "awesome_nested_set's move_to_left_of method isn't implemented in this version of Hyrarchy"
294
+
295
+ # The semantics of left and right don't quite map exactly from
296
+ # awesome_nested_set to Hyrarchy. For the purpose of this method, "left"
297
+ # means "before."
298
+ #
299
+ # If this node isn't a sibling of +other+, its parent will be set to
300
+ # +other+'s parent.
301
+ def move_to_left_of(other)
302
+ # Don't attempt an impossible move.
303
+ if other.is_descendant_of?(self)
304
+ raise ArgumentError, "you can't move a node to the left of one of its descendants"
305
+ end
306
+ # Find the first unused path after +other+'s path.
307
+ open_path = other.send(:encoded_path).next_sibling
308
+ while self.class.exists?(:lft_numer => open_path.numerator, :lft_denom => open_path.denominator)
309
+ open_path = open_path.next_sibling
310
+ end
311
+ # Move +other+, and all nodes following it, down.
312
+ while open_path != other.send(:encoded_path)
313
+ p = open_path.previous_sibling
314
+ n = self.class.send(:find_by_encoded_path, p)
315
+ n.send(:encoded_path=, open_path)
316
+ n.save!
317
+ open_path = p
318
+ end
319
+ puts open_path
320
+ # Insert this node.
321
+ send(:encoded_path=, open_path)
322
+ save!
282
323
  end
283
324
 
284
- def move_to_right_of(other) # :nodoc:
285
- raise NotImplementedError, "awesome_nested_set's move_to_right_of method isn't implemented in this version of Hyrarchy"
325
+ # The semantics of left and right don't quite map exactly from
326
+ # awesome_nested_set to Hyrarchy. For the purpose of this method, "right"
327
+ # means "after."
328
+ #
329
+ # If this node isn't a sibling of +other+, its parent will be set to
330
+ # +other+'s parent.
331
+ def move_to_right_of(other)
332
+ # Don't attempt an impossible move.
333
+ if other.is_descendant_of?(self)
334
+ raise ArgumentError, "you can't move a node to the right of one of its descendants"
335
+ end
336
+ # If +other+ is its parent's last child, we can simply append this node
337
+ # to the parent's children.
338
+ if other == other.parent.children.last
339
+ send(:encoded_path=, other.parent.send(:next_child_encoded_path))
340
+ save!
341
+ else
342
+ # Otherwise, this is equivalent to moving this node to the left of
343
+ # +other+'s right sibling.
344
+ move_to_left_of(other.right_sibling)
345
+ end
286
346
  end
287
347
 
288
348
  # Sets this node's parent to +node+ and calls save!.
@@ -55,6 +55,16 @@ module Hyrarchy
55
55
  parent(false).mediant(self)
56
56
  end
57
57
 
58
+ # Returns the path of the sibling immediately before the node at this path.
59
+ # If this is the path of the first sibling, returns nil.
60
+ def previous_sibling
61
+ p = parent(false)
62
+ return nil if self == p.first_child
63
+ Hyrarchy::EncodedPath(
64
+ numerator - p.numerator,
65
+ denominator - p.denominator)
66
+ end
67
+
58
68
  # Finds the mediant of this fraction and +other+.
59
69
  def mediant(other)
60
70
  Hyrarchy::EncodedPath(
data/lib/hyrarchy.rb CHANGED
@@ -81,6 +81,7 @@ module Hyrarchy
81
81
  before_save :set_encoded_paths
82
82
  before_save :set_parent_id
83
83
  after_save :update_descendant_paths
84
+ after_save :reset_flags
84
85
 
85
86
  named_scope :roots,
86
87
  :conditions => { :parent_id => nil },
@@ -210,6 +211,7 @@ module Hyrarchy
210
211
  # associations.
211
212
  def reload(options = nil) # :nodoc:
212
213
  @cached = {}
214
+ reset_flags
213
215
  super
214
216
  end
215
217
 
@@ -292,8 +294,9 @@ module Hyrarchy
292
294
 
293
295
  # after_save callback to ensure that this node's descendants are updated if
294
296
  # this node has moved.
295
- def update_descendant_paths
297
+ def update_descendant_paths # :nodoc:
296
298
  return true unless @path_has_changed
299
+ children.reload if children.loaded? && children.empty?
297
300
 
298
301
  child_path = encoded_path.first_child
299
302
  children.each do |c|
@@ -304,5 +307,10 @@ module Hyrarchy
304
307
 
305
308
  true
306
309
  end
310
+
311
+ # Resets internal flags after saving.
312
+ def reset_flags # :nodoc:
313
+ @path_has_changed = @new_parent = @make_root = nil
314
+ end
307
315
  end
308
316
  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.2"
4
+ version: "0.3"
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-22 00:00:00 -08:00
12
+ date: 2009-01-11 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies: []
15
15