Skip to content

Commit e7e270f

Browse files
committed
Merge pull request #5 from jheiss/master
InstanceMethods is deprecated in rails 3.2.0
2 parents 5d29a61 + d3cd0e6 commit e7e270f

File tree

1 file changed

+125
-127
lines changed

1 file changed

+125
-127
lines changed

lib/closure_tree/acts_as_tree.rb

+125-127
Original file line numberDiff line numberDiff line change
@@ -66,162 +66,160 @@ def acts_as_tree(options = {})
6666

6767
module Model
6868
extend ActiveSupport::Concern
69-
module InstanceMethods
7069

71-
# Returns true if this node has no parents.
72-
def root?
73-
parent.nil?
74-
end
70+
# Returns true if this node has no parents.
71+
def root?
72+
parent.nil?
73+
end
7574

76-
# Returns true if this node has a parent, and is not a root.
77-
def child?
78-
!parent.nil?
79-
end
75+
# Returns true if this node has a parent, and is not a root.
76+
def child?
77+
!parent.nil?
78+
end
8079

81-
# Returns true if this node has no children.
82-
def leaf?
83-
children.empty?
84-
end
80+
# Returns true if this node has no children.
81+
def leaf?
82+
children.empty?
83+
end
8584

86-
# Returns the farthest ancestor, or self if +root?+
87-
def root
88-
root? ? self : ancestors.last
89-
end
85+
# Returns the farthest ancestor, or self if +root?+
86+
def root
87+
root? ? self : ancestors.last
88+
end
9089

91-
def leaves
92-
return [self] if leaf?
93-
self.class.leaves.where(<<-SQL
90+
def leaves
91+
return [self] if leaf?
92+
self.class.leaves.where(<<-SQL
9493
#{quoted_table_name}.#{self.class.primary_key} IN (
95-
SELECT descendant_id
96-
FROM #{quoted_hierarchy_table_name}
97-
WHERE ancestor_id = #{id})
98-
SQL
99-
)
100-
end
101-
102-
def level
103-
ancestors.size
104-
end
94+
SELECT descendant_id
95+
FROM #{quoted_hierarchy_table_name}
96+
WHERE ancestor_id = #{id})
97+
SQL
98+
)
99+
end
105100

106-
def ancestors
107-
without_self(self_and_ancestors)
108-
end
101+
def level
102+
ancestors.size
103+
end
109104

110-
# Returns an array, root first, of self_and_ancestors' values of the +to_s_column+, which defaults
111-
# to the +name_column+.
112-
# (so child.ancestry_path == +%w{grandparent parent child}+
113-
def ancestry_path(to_s_column = name_column)
114-
self_and_ancestors.reverse.collect { |n| n.send to_s_column.to_sym }
115-
end
105+
def ancestors
106+
without_self(self_and_ancestors)
107+
end
116108

117-
def descendants
118-
without_self(self_and_descendants)
119-
end
109+
# Returns an array, root first, of self_and_ancestors' values of the +to_s_column+, which defaults
110+
# to the +name_column+.
111+
# (so child.ancestry_path == +%w{grandparent parent child}+
112+
def ancestry_path(to_s_column = name_column)
113+
self_and_ancestors.reverse.collect { |n| n.send to_s_column.to_sym }
114+
end
120115

121-
def self_and_siblings
122-
self.class.scoped.where(:parent => parent)
123-
end
116+
def descendants
117+
without_self(self_and_descendants)
118+
end
124119

125-
def siblings
126-
without_self(self_and_siblings)
127-
end
120+
def self_and_siblings
121+
self.class.scoped.where(:parent => parent)
122+
end
128123

129-
# Alias for appending to the children collection.
130-
# You can also add directly to the children collection, if you'd prefer.
131-
def add_child(child_node)
132-
children << child_node
133-
child_node
134-
end
124+
def siblings
125+
without_self(self_and_siblings)
126+
end
135127

136-
# Find a child node whose +ancestry_path+ minus self.ancestry_path is +path+.
137-
def find_by_path(path)
138-
path = [path] unless path.is_a? Enumerable
139-
node = self
140-
while (!path.empty? && node)
141-
node = node.children.send("find_by_#{name_column}", path.shift)
142-
end
143-
node
144-
end
128+
# Alias for appending to the children collection.
129+
# You can also add directly to the children collection, if you'd prefer.
130+
def add_child(child_node)
131+
children << child_node
132+
child_node
133+
end
145134

146-
# Find a child node whose +ancestry_path+ minus self.ancestry_path is +path+
147-
def find_or_create_by_path(path, attributes = {})
148-
path = [path] unless path.is_a? Enumerable
149-
node = self
150-
attrs = {}
151-
attrs[:type] = self.type if ct_subclass? && ct_has_type?
152-
path.each do |name|
153-
attrs[name_sym] = name
154-
child = node.children.where(attrs).first
155-
unless child
156-
child = self.class.new(attributes.merge attrs)
157-
node.children << child
158-
end
159-
node = child
160-
end
161-
node
135+
# Find a child node whose +ancestry_path+ minus self.ancestry_path is +path+.
136+
def find_by_path(path)
137+
path = [path] unless path.is_a? Enumerable
138+
node = self
139+
while (!path.empty? && node)
140+
node = node.children.send("find_by_#{name_column}", path.shift)
162141
end
142+
node
143+
end
163144

164-
protected
165-
166-
def acts_as_tree_before_save
167-
@was_new_record = new_record?
168-
if changes[parent_column_name] &&
169-
parent.present? &&
170-
parent.self_and_ancestors.include?(self)
171-
# TODO: raise Ouroboros or Philip J. Fry error:
172-
raise ActiveRecord::ActiveRecordError "You cannot add an ancestor as a descendant"
145+
# Find a child node whose +ancestry_path+ minus self.ancestry_path is +path+
146+
def find_or_create_by_path(path, attributes = {})
147+
path = [path] unless path.is_a? Enumerable
148+
node = self
149+
attrs = {}
150+
attrs[:type] = self.type if ct_subclass? && ct_has_type?
151+
path.each do |name|
152+
attrs[name_sym] = name
153+
child = node.children.where(attrs).first
154+
unless child
155+
child = self.class.new(attributes.merge attrs)
156+
node.children << child
173157
end
158+
node = child
174159
end
160+
node
161+
end
175162

176-
def acts_as_tree_after_save
177-
rebuild! if changes[parent_column_name] || @was_new_record
178-
end
163+
protected
179164

180-
def rebuild!
181-
delete_hierarchy_references unless @was_new_record
182-
hierarchy_class.create!(:ancestor => self, :descendant => self, :generations => 0)
183-
unless root?
184-
connection.execute <<-SQL
185-
INSERT INTO #{quoted_hierarchy_table_name}
186-
(ancestor_id, descendant_id, generations)
187-
SELECT x.ancestor_id, #{id}, x.generations + 1
188-
FROM #{quoted_hierarchy_table_name} x
189-
WHERE x.descendant_id = #{self._parent_id}
190-
SQL
191-
end
192-
children.each { |c| c.rebuild! }
165+
def acts_as_tree_before_save
166+
@was_new_record = new_record?
167+
if changes[parent_column_name] &&
168+
parent.present? &&
169+
parent.self_and_ancestors.include?(self)
170+
# TODO: raise Ouroboros or Philip J. Fry error:
171+
raise ActiveRecord::ActiveRecordError "You cannot add an ancestor as a descendant"
193172
end
173+
end
194174

195-
def acts_as_tree_before_destroy
196-
delete_hierarchy_references
197-
if closure_tree_options[:dependent] == :nullify
198-
children.each { |c| c.rebuild! }
199-
end
200-
end
175+
def acts_as_tree_after_save
176+
rebuild! if changes[parent_column_name] || @was_new_record
177+
end
201178

202-
def delete_hierarchy_references
203-
# The crazy double-wrapped sub-subselect works around MySQL's limitation of subselects on the same table that is being mutated.
204-
# It shouldn't affect performance of postgresql.
205-
# See http://dev.mysql.com/doc/refman/5.0/en/subquery-errors.html
179+
def rebuild!
180+
delete_hierarchy_references unless @was_new_record
181+
hierarchy_class.create!(:ancestor => self, :descendant => self, :generations => 0)
182+
unless root?
206183
connection.execute <<-SQL
207-
DELETE FROM #{quoted_hierarchy_table_name}
208-
WHERE descendant_id IN (
209-
SELECT DISTINCT descendant_id
210-
FROM ( SELECT descendant_id
211-
FROM #{quoted_hierarchy_table_name}
212-
WHERE ancestor_id = #{id}
213-
) AS x )
214-
OR descendant_id = #{id}
184+
INSERT INTO #{quoted_hierarchy_table_name}
185+
(ancestor_id, descendant_id, generations)
186+
SELECT x.ancestor_id, #{id}, x.generations + 1
187+
FROM #{quoted_hierarchy_table_name} x
188+
WHERE x.descendant_id = #{self._parent_id}
215189
SQL
216190
end
191+
children.each { |c| c.rebuild! }
192+
end
217193

218-
def without_self(scope)
219-
scope.where(["#{quoted_table_name}.#{self.class.primary_key} != ?", self])
194+
def acts_as_tree_before_destroy
195+
delete_hierarchy_references
196+
if closure_tree_options[:dependent] == :nullify
197+
children.each { |c| c.rebuild! }
220198
end
199+
end
221200

222-
def _parent_id
223-
send(parent_column_name)
224-
end
201+
def delete_hierarchy_references
202+
# The crazy double-wrapped sub-subselect works around MySQL's limitation of subselects on the same table that is being mutated.
203+
# It shouldn't affect performance of postgresql.
204+
# See http://dev.mysql.com/doc/refman/5.0/en/subquery-errors.html
205+
connection.execute <<-SQL
206+
DELETE FROM #{quoted_hierarchy_table_name}
207+
WHERE descendant_id IN (
208+
SELECT DISTINCT descendant_id
209+
FROM ( SELECT descendant_id
210+
FROM #{quoted_hierarchy_table_name}
211+
WHERE ancestor_id = #{id}
212+
) AS x )
213+
OR descendant_id = #{id}
214+
SQL
215+
end
216+
217+
def without_self(scope)
218+
scope.where(["#{quoted_table_name}.#{self.class.primary_key} != ?", self])
219+
end
220+
221+
def _parent_id
222+
send(parent_column_name)
225223
end
226224

227225
module ClassMethods

0 commit comments

Comments
 (0)