awesome_nested_set 1.4.4 → 2.0.0

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.
@@ -0,0 +1,5 @@
1
+ 2.0.0.pre
2
+ * Expect Rails 3
3
+ * Changed how callbacks work. Returning false in a before_move action does not block save operations. Use a validation or exception in the callback if you need that.
4
+ * Switched to RSpec
5
+ * Remove use of Comparable
@@ -1,4 +1,4 @@
1
- Copyright (c) 2007 [name of plugin creator]
1
+ Copyright (c) 2007-2011 Collective Idea
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
@@ -1,6 +1,8 @@
1
1
  = AwesomeNestedSet
2
2
 
3
- Awesome Nested Set is an implementation of the nested set pattern for ActiveRecord models. It is replacement for acts_as_nested_set and BetterNestedSet, but awesomer. It supports Rails 2.1 and later.
3
+ Awesome Nested Set is an implementation of the nested set pattern for ActiveRecord models. It is replacement for acts_as_nested_set and BetterNestedSet, but more awesome.
4
+
5
+ Version 2 supports Rails 3. Gem versions prior to 2.0 support Rails 2.
4
6
 
5
7
  == What makes this so awesome?
6
8
 
@@ -8,10 +10,10 @@ This is a new implementation of nested set based off of BetterNestedSet that fix
8
10
 
9
11
  == Installation
10
12
 
11
- Install as a plugin:
13
+ Add to your Gemfile:
14
+
15
+ gem 'awesome_nested_set'
12
16
 
13
- script/plugin install git://github.com/collectiveidea/awesome_nested_set.git
14
-
15
17
  == Usage
16
18
 
17
19
  To make use of awesome_nested_set, your model needs to have 3 fields: lft, rgt, and parent_id:
@@ -36,20 +38,20 @@ Enable the nested set functionality by declaring acts_as_nested_set on your mode
36
38
  class Category < ActiveRecord::Base
37
39
  acts_as_nested_set
38
40
  end
39
-
40
- Run `rake rdoc` to generate the API docs and see CollectiveIdea::Acts::NestedSet::SingletonMethods for more info.
41
+
42
+ Run `rake rdoc` to generate the API docs and see CollectiveIdea::Acts::NestedSet::Model::SingletonMethods for more info.
41
43
 
42
44
  == Conversion from other trees
43
45
 
44
46
  Coming from acts_as_tree or another system where you only have a parent_id? No problem. Simply add the lft & rgt fields as above, and then run
45
47
 
46
48
  Category.rebuild!
47
-
48
- Your tree be converted to a valid nested set. Awesome!
49
+
50
+ Your tree will be converted to a valid nested set. Awesome!
49
51
 
50
52
  == View Helper
51
53
 
52
- The view helper is called #nested_set_options.
54
+ The view helper is called #nested_set_options.
53
55
 
54
56
  Example usage:
55
57
 
@@ -61,12 +63,7 @@ See CollectiveIdea::Acts::NestedSet::Helper for more information about the helpe
61
63
 
62
64
  == References
63
65
 
64
- You can learn more about nested sets at:
65
-
66
- http://www.dbmsmag.com/9603d06.html
67
- http://threebit.net/tutorials/nestedset/tutorial1.html
68
- http://api.rubyonrails.com/classes/ActiveRecord/Acts/NestedSet/ClassMethods.html
69
- http://opensource.symetrie.com/trac/better_nested_set/
66
+ You can learn more about nested sets at: http://threebit.net/tutorials/nestedset/tutorial1.html
70
67
 
71
68
  == How to contribute
72
69
 
@@ -1,578 +1,7 @@
1
- module CollectiveIdea #:nodoc:
2
- module Acts #:nodoc:
3
- module NestedSet #:nodoc:
4
- def self.included(base)
5
- base.extend(SingletonMethods)
6
- end
1
+ require 'awesome_nested_set/awesome_nested_set'
2
+ ActiveRecord::Base.send :extend, CollectiveIdea::Acts::NestedSet
7
3
 
8
- # This acts provides Nested Set functionality. Nested Set is a smart way to implement
9
- # an _ordered_ tree, with the added feature that you can select the children and all of their
10
- # descendants with a single query. The drawback is that insertion or move need some complex
11
- # sql queries. But everything is done here by this module!
12
- #
13
- # Nested sets are appropriate each time you want either an orderd tree (menus,
14
- # commercial categories) or an efficient way of querying big trees (threaded posts).
15
- #
16
- # == API
17
- #
18
- # Methods names are aligned with acts_as_tree as much as possible to make replacment from one
19
- # by another easier.
20
- #
21
- # item.children.create(:name => "child1")
22
- #
23
- module SingletonMethods
24
- # Configuration options are:
25
- #
26
- # * +:parent_column+ - specifies the column name to use for keeping the position integer (default: parent_id)
27
- # * +:left_column+ - column name for left boundry data, default "lft"
28
- # * +:right_column+ - column name for right boundry data, default "rgt"
29
- # * +:scope+ - restricts what is to be considered a list. Given a symbol, it'll attach "_id"
30
- # (if it hasn't been already) and use that as the foreign key restriction. You
31
- # can also pass an array to scope by multiple attributes.
32
- # Example: <tt>acts_as_nested_set :scope => [:notable_id, :notable_type]</tt>
33
- # * +:dependent+ - behavior for cascading destroy. If set to :destroy, all the
34
- # child objects are destroyed alongside this object by calling their destroy
35
- # method. If set to :delete_all (default), all the child objects are deleted
36
- # without calling their destroy method.
37
- #
38
- # See CollectiveIdea::Acts::NestedSet::ClassMethods for a list of class methods and
39
- # CollectiveIdea::Acts::NestedSet::InstanceMethods for a list of instance methods added
40
- # to acts_as_nested_set models
41
- def acts_as_nested_set(options = {})
42
- options = {
43
- :parent_column => 'parent_id',
44
- :left_column => 'lft',
45
- :right_column => 'rgt',
46
- :dependent => :delete_all, # or :destroy
47
- }.merge(options)
48
-
49
- if options[:scope].is_a?(Symbol) && options[:scope].to_s !~ /_id$/
50
- options[:scope] = "#{options[:scope]}_id".intern
51
- end
52
-
53
- write_inheritable_attribute :acts_as_nested_set_options, options
54
- class_inheritable_reader :acts_as_nested_set_options
55
-
56
- unless self.is_a?(ClassMethods)
57
- include Comparable
58
- include Columns
59
- include InstanceMethods
60
- extend Columns
61
- extend ClassMethods
62
-
63
- belongs_to :parent, :class_name => self.base_class.to_s,
64
- :foreign_key => parent_column_name
65
- has_many :children, :class_name => self.base_class.to_s,
66
- :foreign_key => parent_column_name, :order => quoted_left_column_name
67
-
68
- attr_accessor :skip_before_destroy
69
-
70
- # no bulk assignment
71
- if accessible_attributes.blank?
72
- attr_protected left_column_name.intern, right_column_name.intern
73
- end
74
-
75
- before_create :set_default_left_and_right
76
- before_save :store_new_parent
77
- after_save :move_to_new_parent
78
- before_destroy :destroy_descendants
79
-
80
- # no assignment to structure fields
81
- [left_column_name, right_column_name].each do |column|
82
- module_eval <<-"end_eval", __FILE__, __LINE__
83
- def #{column}=(x)
84
- raise ActiveRecord::ActiveRecordError, "Unauthorized assignment to #{column}: it's an internal field handled by acts_as_nested_set code, use move_to_* methods instead."
85
- end
86
- end_eval
87
- end
88
-
89
- named_scope :roots, :conditions => {parent_column_name => nil}, :order => quoted_left_column_name
90
- named_scope :leaves, :conditions => "#{quoted_right_column_name} - #{quoted_left_column_name} = 1", :order => quoted_left_column_name
91
-
92
- define_callbacks("before_move", "after_move")
93
- end
94
-
95
- end
96
-
97
- end
98
-
99
- module ClassMethods
100
-
101
- # Returns the first root
102
- def root
103
- roots.find(:first)
104
- end
105
-
106
- def valid?
107
- left_and_rights_valid? && no_duplicates_for_columns? && all_roots_valid?
108
- end
109
-
110
- def left_and_rights_valid?
111
- count(
112
- :joins => "LEFT OUTER JOIN #{quoted_table_name} AS parent ON " +
113
- "#{quoted_table_name}.#{quoted_parent_column_name} = parent.#{primary_key}",
114
- :conditions =>
115
- "#{quoted_table_name}.#{quoted_left_column_name} IS NULL OR " +
116
- "#{quoted_table_name}.#{quoted_right_column_name} IS NULL OR " +
117
- "#{quoted_table_name}.#{quoted_left_column_name} >= " +
118
- "#{quoted_table_name}.#{quoted_right_column_name} OR " +
119
- "(#{quoted_table_name}.#{quoted_parent_column_name} IS NOT NULL AND " +
120
- "(#{quoted_table_name}.#{quoted_left_column_name} <= parent.#{quoted_left_column_name} OR " +
121
- "#{quoted_table_name}.#{quoted_right_column_name} >= parent.#{quoted_right_column_name}))"
122
- ) == 0
123
- end
124
-
125
- def no_duplicates_for_columns?
126
- scope_string = Array(acts_as_nested_set_options[:scope]).map do |c|
127
- connection.quote_column_name(c)
128
- end.push(nil).join(", ")
129
- [quoted_left_column_name, quoted_right_column_name].all? do |column|
130
- # No duplicates
131
- find(:first,
132
- :select => "#{scope_string}#{column}, COUNT(#{column})",
133
- :group => "#{scope_string}#{column}
134
- HAVING COUNT(#{column}) > 1").nil?
135
- end
136
- end
137
-
138
- # Wrapper for each_root_valid? that can deal with scope.
139
- def all_roots_valid?
140
- if acts_as_nested_set_options[:scope]
141
- roots(:group => scope_column_names).group_by{|record| scope_column_names.collect{|col| record.send(col.to_sym)}}.all? do |scope, grouped_roots|
142
- each_root_valid?(grouped_roots)
143
- end
144
- else
145
- each_root_valid?(roots)
146
- end
147
- end
148
-
149
- def each_root_valid?(roots_to_validate)
150
- left = right = 0
151
- roots_to_validate.all? do |root|
152
- returning(root.left > left && root.right > right) do
153
- left = root.left
154
- right = root.right
155
- end
156
- end
157
- end
158
-
159
- # Rebuilds the left & rights if unset or invalid. Also very useful for converting from acts_as_tree.
160
- def rebuild!
161
- # Don't rebuild a valid tree.
162
- return true if valid?
163
-
164
- scope = lambda{|node|}
165
- if acts_as_nested_set_options[:scope]
166
- scope = lambda{|node|
167
- scope_column_names.inject(""){|str, column_name|
168
- str << "AND #{connection.quote_column_name(column_name)} = #{connection.quote(node.send(column_name.to_sym))} "
169
- }
170
- }
171
- end
172
- indices = {}
173
-
174
- set_left_and_rights = lambda do |node|
175
- # set left
176
- node[left_column_name] = indices[scope.call(node)] += 1
177
- # find
178
- find(:all, :conditions => ["#{quoted_parent_column_name} = ? #{scope.call(node)}", node], :order => "#{quoted_left_column_name}, #{quoted_right_column_name}, id").each{|n| set_left_and_rights.call(n) }
179
- # set right
180
- node[right_column_name] = indices[scope.call(node)] += 1
181
- node.save!
182
- end
183
-
184
- # Find root node(s)
185
- root_nodes = find(:all, :conditions => "#{quoted_parent_column_name} IS NULL", :order => "#{quoted_left_column_name}, #{quoted_right_column_name}, id").each do |root_node|
186
- # setup index for this scope
187
- indices[scope.call(root_node)] ||= 0
188
- set_left_and_rights.call(root_node)
189
- end
190
- end
191
-
192
- # Iterates over tree elements and determines the current level in the tree.
193
- # Only accepts default ordering, odering by an other column than lft
194
- # does not work. This method is much more efficent than calling level
195
- # because it doesn't require any additional database queries.
196
- #
197
- # Example:
198
- # Category.each_with_level(Category.root.self_and_descendants) do |o, level|
199
- #
200
- def each_with_level(objects)
201
- path = [nil]
202
- objects.each do |o|
203
- if o.parent_id != path.last
204
- # we are on a new level, did we decent or ascent?
205
- if path.include?(o.parent_id)
206
- # remove wrong wrong tailing paths elements
207
- path.pop while path.last != o.parent_id
208
- else
209
- path << o.parent_id
210
- end
211
- end
212
- yield(o, path.length - 1)
213
- end
214
- end
215
- end
216
-
217
- # Mixed into both classes and instances to provide easy access to the column names
218
- module Columns
219
- def left_column_name
220
- acts_as_nested_set_options[:left_column]
221
- end
222
-
223
- def right_column_name
224
- acts_as_nested_set_options[:right_column]
225
- end
226
-
227
- def parent_column_name
228
- acts_as_nested_set_options[:parent_column]
229
- end
230
-
231
- def scope_column_names
232
- Array(acts_as_nested_set_options[:scope])
233
- end
234
-
235
- def quoted_left_column_name
236
- connection.quote_column_name(left_column_name)
237
- end
238
-
239
- def quoted_right_column_name
240
- connection.quote_column_name(right_column_name)
241
- end
242
-
243
- def quoted_parent_column_name
244
- connection.quote_column_name(parent_column_name)
245
- end
246
-
247
- def quoted_scope_column_names
248
- scope_column_names.collect {|column_name| connection.quote_column_name(column_name) }
249
- end
250
- end
251
-
252
- # Any instance method that returns a collection makes use of Rails 2.1's named_scope (which is bundled for Rails 2.0), so it can be treated as a finder.
253
- #
254
- # category.self_and_descendants.count
255
- # category.ancestors.find(:all, :conditions => "name like '%foo%'")
256
- module InstanceMethods
257
- # Value of the parent column
258
- def parent_id
259
- self[parent_column_name]
260
- end
261
-
262
- # Value of the left column
263
- def left
264
- self[left_column_name]
265
- end
266
-
267
- # Value of the right column
268
- def right
269
- self[right_column_name]
270
- end
271
-
272
- # Returns true if this is a root node.
273
- def root?
274
- parent_id.nil?
275
- end
276
-
277
- def leaf?
278
- !new_record? && right - left == 1
279
- end
280
-
281
- # Returns true is this is a child node
282
- def child?
283
- !parent_id.nil?
284
- end
285
-
286
- # order by left column
287
- def <=>(x)
288
- left <=> x.left
289
- end
290
-
291
- # Redefine to act like active record
292
- def ==(comparison_object)
293
- comparison_object.equal?(self) ||
294
- (comparison_object.instance_of?(self.class) &&
295
- comparison_object.id == id &&
296
- !comparison_object.new_record?)
297
- end
298
-
299
- # Returns root
300
- def root
301
- self_and_ancestors.find(:first)
302
- end
303
-
304
- # Returns the array of all parents and self
305
- def self_and_ancestors
306
- nested_set_scope.scoped :conditions => [
307
- "#{self.class.quoted_table_name}.#{quoted_left_column_name} <= ? AND #{self.class.quoted_table_name}.#{quoted_right_column_name} >= ?", left, right
308
- ]
309
- end
310
-
311
- # Returns an array of all parents
312
- def ancestors
313
- without_self self_and_ancestors
314
- end
315
-
316
- # Returns the array of all children of the parent, including self
317
- def self_and_siblings
318
- nested_set_scope.scoped :conditions => {parent_column_name => parent_id}
319
- end
320
-
321
- # Returns the array of all children of the parent, except self
322
- def siblings
323
- without_self self_and_siblings
324
- end
325
-
326
- # Returns a set of all of its nested children which do not have children
327
- def leaves
328
- descendants.scoped :conditions => "#{self.class.quoted_table_name}.#{quoted_right_column_name} - #{self.class.quoted_table_name}.#{quoted_left_column_name} = 1"
329
- end
330
-
331
- # Returns the level of this object in the tree
332
- # root level is 0
333
- def level
334
- parent_id.nil? ? 0 : ancestors.count
335
- end
336
-
337
- # Returns a set of itself and all of its nested children
338
- def self_and_descendants
339
- nested_set_scope.scoped :conditions => [
340
- "#{self.class.quoted_table_name}.#{quoted_left_column_name} >= ? AND #{self.class.quoted_table_name}.#{quoted_right_column_name} <= ?", left, right
341
- ]
342
- end
343
-
344
- # Returns a set of all of its children and nested children
345
- def descendants
346
- without_self self_and_descendants
347
- end
348
-
349
- def is_descendant_of?(other)
350
- other.left < self.left && self.left < other.right && same_scope?(other)
351
- end
352
-
353
- def is_or_is_descendant_of?(other)
354
- other.left <= self.left && self.left < other.right && same_scope?(other)
355
- end
356
-
357
- def is_ancestor_of?(other)
358
- self.left < other.left && other.left < self.right && same_scope?(other)
359
- end
360
-
361
- def is_or_is_ancestor_of?(other)
362
- self.left <= other.left && other.left < self.right && same_scope?(other)
363
- end
364
-
365
- # Check if other model is in the same scope
366
- def same_scope?(other)
367
- Array(acts_as_nested_set_options[:scope]).all? do |attr|
368
- self.send(attr) == other.send(attr)
369
- end
370
- end
371
-
372
- # Find the first sibling to the left
373
- def left_sibling
374
- siblings.find(:first, :conditions => ["#{self.class.quoted_table_name}.#{quoted_left_column_name} < ?", left],
375
- :order => "#{self.class.quoted_table_name}.#{quoted_left_column_name} DESC")
376
- end
377
-
378
- # Find the first sibling to the right
379
- def right_sibling
380
- siblings.find(:first, :conditions => ["#{self.class.quoted_table_name}.#{quoted_left_column_name} > ?", left])
381
- end
382
-
383
- # Shorthand method for finding the left sibling and moving to the left of it.
384
- def move_left
385
- move_to_left_of left_sibling
386
- end
387
-
388
- # Shorthand method for finding the right sibling and moving to the right of it.
389
- def move_right
390
- move_to_right_of right_sibling
391
- end
392
-
393
- # Move the node to the left of another node (you can pass id only)
394
- def move_to_left_of(node)
395
- move_to node, :left
396
- end
397
-
398
- # Move the node to the left of another node (you can pass id only)
399
- def move_to_right_of(node)
400
- move_to node, :right
401
- end
402
-
403
- # Move the node to the child of another node (you can pass id only)
404
- def move_to_child_of(node)
405
- move_to node, :child
406
- end
407
-
408
- # Move the node to root nodes
409
- def move_to_root
410
- move_to nil, :root
411
- end
412
-
413
- def move_possible?(target)
414
- self != target && # Can't target self
415
- same_scope?(target) && # can't be in different scopes
416
- # !(left..right).include?(target.left..target.right) # this needs tested more
417
- # detect impossible move
418
- !((left <= target.left && right >= target.left) or (left <= target.right && right >= target.right))
419
- end
420
-
421
- def to_text
422
- self_and_descendants.map do |node|
423
- "#{'*'*(node.level+1)} #{node.id} #{node.to_s} (#{node.parent_id}, #{node.left}, #{node.right})"
424
- end.join("\n")
425
- end
426
-
427
- protected
428
-
429
- def without_self(scope)
430
- scope.scoped :conditions => ["#{self.class.quoted_table_name}.#{self.class.primary_key} != ?", self]
431
- end
432
-
433
- # All nested set queries should use this nested_set_scope, which performs finds on
434
- # the base ActiveRecord class, using the :scope declared in the acts_as_nested_set
435
- # declaration.
436
- def nested_set_scope
437
- options = {:order => quoted_left_column_name}
438
- scopes = Array(acts_as_nested_set_options[:scope])
439
- options[:conditions] = scopes.inject({}) do |conditions,attr|
440
- conditions.merge attr => self[attr]
441
- end unless scopes.empty?
442
- self.class.base_class.scoped options
443
- end
444
-
445
- def store_new_parent
446
- @move_to_new_parent_id = send("#{parent_column_name}_changed?") ? parent_id : false
447
- true # force callback to return true
448
- end
449
-
450
- def move_to_new_parent
451
- if @move_to_new_parent_id.nil?
452
- move_to_root
453
- elsif @move_to_new_parent_id
454
- move_to_child_of(@move_to_new_parent_id)
455
- end
456
- end
457
-
458
- # on creation, set automatically lft and rgt to the end of the tree
459
- def set_default_left_and_right
460
- maxright = nested_set_scope.maximum(right_column_name) || 0
461
- # adds the new node to the right of all existing nodes
462
- self[left_column_name] = maxright + 1
463
- self[right_column_name] = maxright + 2
464
- end
465
-
466
- # Prunes a branch off of the tree, shifting all of the elements on the right
467
- # back to the left so the counts still work.
468
- def destroy_descendants
469
- return if right.nil? || left.nil? || skip_before_destroy
470
-
471
- self.class.base_class.transaction do
472
- if acts_as_nested_set_options[:dependent] == :destroy
473
- descendants.each do |model|
474
- model.skip_before_destroy = true
475
- model.destroy
476
- end
477
- else
478
- nested_set_scope.delete_all(
479
- ["#{quoted_left_column_name} > ? AND #{quoted_right_column_name} < ?",
480
- left, right]
481
- )
482
- end
483
-
484
- # update lefts and rights for remaining nodes
485
- diff = right - left + 1
486
- nested_set_scope.update_all(
487
- ["#{quoted_left_column_name} = (#{quoted_left_column_name} - ?)", diff],
488
- ["#{quoted_left_column_name} > ?", right]
489
- )
490
- nested_set_scope.update_all(
491
- ["#{quoted_right_column_name} = (#{quoted_right_column_name} - ?)", diff],
492
- ["#{quoted_right_column_name} > ?", right]
493
- )
494
-
495
- # Don't allow multiple calls to destroy to corrupt the set
496
- self.skip_before_destroy = true
497
- end
498
- end
499
-
500
- # reload left, right, and parent
501
- def reload_nested_set
502
- reload(:select => "#{quoted_left_column_name}, " +
503
- "#{quoted_right_column_name}, #{quoted_parent_column_name}")
504
- end
505
-
506
- def move_to(target, position)
507
- raise ActiveRecord::ActiveRecordError, "You cannot move a new node" if self.new_record?
508
- return if run_callbacks(:before_move) == false
509
- transaction do
510
- if target.is_a? self.class.base_class
511
- target.reload_nested_set
512
- elsif position != :root
513
- # load object if node is not an object
514
- target = nested_set_scope.find(target)
515
- end
516
- self.reload_nested_set
517
-
518
- unless position == :root || move_possible?(target)
519
- raise ActiveRecord::ActiveRecordError, "Impossible move, target node cannot be inside moved tree."
520
- end
521
-
522
- bound = case position
523
- when :child; target[right_column_name]
524
- when :left; target[left_column_name]
525
- when :right; target[right_column_name] + 1
526
- when :root; 1
527
- else raise ActiveRecord::ActiveRecordError, "Position should be :child, :left, :right or :root ('#{position}' received)."
528
- end
529
-
530
- if bound > self[right_column_name]
531
- bound = bound - 1
532
- other_bound = self[right_column_name] + 1
533
- else
534
- other_bound = self[left_column_name] - 1
535
- end
536
-
537
- # there would be no change
538
- return if bound == self[right_column_name] || bound == self[left_column_name]
539
-
540
- # we have defined the boundaries of two non-overlapping intervals,
541
- # so sorting puts both the intervals and their boundaries in order
542
- a, b, c, d = [self[left_column_name], self[right_column_name], bound, other_bound].sort
543
-
544
- new_parent = case position
545
- when :child; target.id
546
- when :root; nil
547
- else target[parent_column_name]
548
- end
549
-
550
- self.class.base_class.update_all([
551
- "#{quoted_left_column_name} = CASE " +
552
- "WHEN #{quoted_left_column_name} BETWEEN :a AND :b " +
553
- "THEN #{quoted_left_column_name} + :d - :b " +
554
- "WHEN #{quoted_left_column_name} BETWEEN :c AND :d " +
555
- "THEN #{quoted_left_column_name} + :a - :c " +
556
- "ELSE #{quoted_left_column_name} END, " +
557
- "#{quoted_right_column_name} = CASE " +
558
- "WHEN #{quoted_right_column_name} BETWEEN :a AND :b " +
559
- "THEN #{quoted_right_column_name} + :d - :b " +
560
- "WHEN #{quoted_right_column_name} BETWEEN :c AND :d " +
561
- "THEN #{quoted_right_column_name} + :a - :c " +
562
- "ELSE #{quoted_right_column_name} END, " +
563
- "#{quoted_parent_column_name} = CASE " +
564
- "WHEN #{self.class.base_class.primary_key} = :id THEN :new_parent " +
565
- "ELSE #{quoted_parent_column_name} END",
566
- {:a => a, :b => b, :c => c, :d => d, :id => self.id, :new_parent => new_parent}
567
- ], nested_set_scope.proxy_options[:conditions])
568
- end
569
- target.reload_nested_set if target
570
- self.reload_nested_set
571
- run_callbacks(:after_move)
572
- end
573
-
574
- end
575
-
576
- end
577
- end
578
- end
4
+ if defined?(ActionView)
5
+ require 'awesome_nested_set/helper'
6
+ ActionView::Base.send :include, CollectiveIdea::Acts::NestedSet::Helper
7
+ end