# 新手问题 是否可改造成递归方法

xeruzo · 2019年02月20日 · 最后由 lyb124553153 回复于 2019年02月21日 · 1037 次阅读

employee 的上下级关系大概是个树结构，但是经过一段使用后有部分比较混乱，旧的递归方法变成死循环了

``````
# 这个是在整数类型中自己加的方法，结果是用整数获取Employee对象，如 Employee.find(1) == 1.to_employee
def to_employee
Employee.find(xx)
end

class Employee
# 属性 id , max_level
attr_accessor :id, :max_level

# 获取的直属下级的员工，返回结果是一个一维数组
def all_sub_ids
[1,2,3,4,5,6.....]
end

# 获取所有下属的员工id现在如下
# max_level > 1的才会需要找all_sub_ids
def get_all_subs
result = []
sub_ids_1 = [id].map{|n| n.to_employee.all_sub_ids}.flatten.compact - result
return result if sub_ids_1.blank?
result += sub_ids_1
sub_ids_2 = sub_ids_1.map{|n| n.to_employee.all_sub_ids}.flatten.compact - result
return result if sub_ids_2.blank?
result += sub_ids_2
sub_ids_3 = sub_ids_2.map{|n| n.to_employee.all_sub_ids}.flatten.compact - result
return result if sub_ids_3.blank?
result += sub_ids_3
sub_ids_4 = sub_ids_3.map{|n| n.to_employee.all_sub_ids}.flatten.compact - result
return result if sub_ids_4.blank?
result += sub_ids_4
sub_ids_5 = sub_ids_4.map{|n| n.to_employee.all_sub_ids}.flatten.compact - result
return result if sub_ids_5.blank?
result += sub_ids_5
sub_ids_6 = sub_ids_5.map{|n| n.to_employee.all_sub_ids}.flatten.compact - result
return result if sub_ids_6.blank?
result += sub_ids_6
sub_ids_7 = sub_ids_6.map{|n| n.to_employee.all_sub_ids}.flatten.compact - result
return result if sub_ids_7.blank?
result += sub_ids_7
sub_ids_8 = sub_ids_7.map{|n| n.to_employee.all_sub_ids}.flatten.compact - result
return result if sub_ids_8.blank?
result += sub_ids_8
sub_ids_9 = sub_ids_8.map{|n| n.to_employee.all_sub_ids}.flatten.compact - result
return result if sub_ids_9.blank?
result += sub_ids_9
result.uniq.compact
end

end

``````

``````def get_all_subs
ids = [id]
ids.each do |id|
sub_ids = id.to_employee.all_sub_ids
ids.push(*sub_ids) if sub_ids.present?
end
return ids
end
``````
spike76 回复

``````def get_all_subs
ids = [self.id]
ids.each do |id|
id.to_employee.all_sub_ids.each{|e_id| ids.push(e_id) unless ids.include?(e_id)}
end
return ids
end
``````

``````def descendants
children.each_with_object(children.to_a) {|child, arr|
arr.concat child.descendants
}.uniq
end
# 假设当前借点是root 调用方法就是 root.descendants，这里返回的对象是AR数组，所以可以继续调用rails的方法
``````

``````#
def descendants(*fields)
subfields = fields.map { |e| "tablename.#{e}" }

ApplicationRecord.connection.execute("
WITH RECURSIVE descendants(#{fields.join(',')}) AS (
SELECT #{fields.join(',')} FROM tablename WHERE id = #{id}
UNION
SELECT #{subfields.join(',')} FROM tablename JOIN descendants ON tablename.parent_id = descendants.id
)
SELECT * FROM descendants;
")
end

# 传入的参数是你需要返回的字段，假设你用parent_id 去表示你的employee 的父子关系 ,这个方法返回的数组，所以不能调用rails的方法
``````