我有一个rails应用程序,其中一个资源称为“组织”,组织可以拥有任意数量的子组织。管理这个,在数据库中我有每个组织条目的父ID。
现在,我的组织模型中有一个方法可以构建所有组织树:
def Organization.build_org_trees_wrapper
parent_nodes = []
parent_orgs = Organization.where(:parent_id => nil)
parent_orgs.each do |org|
parent_node = MyNode.new(org.id, org.name)
parent_node.children_nodes = self.build_org_tree(parent_node)
parent_nodes << parent_node
end
return parent_nodes
end
def Organization.build_org_tree(org_node)
ret = []
org_id = org_node.id
children = Organization.where(:parent_id => org_id)
if !children.empty?
children.each do |child|
child_node = MyNode.new(child.id, child.name)
ret << child_node
child_node.parent_node = org_node
child_node.root_id = root_id
child_node.children_nodes.concat(build_org_tree(child_node))
end
else
return []
end
return ret
end
在控制台中测试后,它可以满足我的需求。到现在为止还挺好。但是,现在要实际使用我创建的这个东西,我想把它放在某个地方,这样它至少有点用处。这可能意味着两件事:
好:
通过调用after_initialize()将其放入实例变量中。我试过这个并且不能让它工作,因为它总是返回nil:
class Organization < ActiveRecord::Base
after_initialize :set_tree
@trees = nil
def set_tree
@trees = self.build_org_trees_wrapper
end
真棒
以某种方式将此小狗存储在会话变量,缓存或键值存储中,以便我始终可以访问它。如果有可能的话,我也会喜欢有关如何做到这一点的建议。
我在这里也有点头脑,所以我欢迎任何批评我的方法。
编辑(忘记我的节点类):
class MyNode
attr_accessor :id, :name, :parent_node, :children_nodes, :root_id
@id = 0
@name = ""
@parent_node = nil
@children_nodes = []
@root_id = 0
def initialize(id, name)
@id = id
@name = name
@children_nodes = []
end
def to_s
return "Name: #{self.name} Org-id: #{self.id}"
end
end
答案 0 :(得分:0)
虽然自己尝试并实现所有这些逻辑是好的(为了学习),但我更喜欢使用gem
来实现这种功能。有多种选择。我个人使用ancestory gem
(https://github.com/stefankroes/ancestry)来表示这种应用。我觉得这个宝石似乎不能与Rails 4一起使用,但是如上所述:Does The Ancestry Gem Work With Rails 4?。
您可以在此SO问题/答案中找到更多选项:acts_as_tree vs ancestry gem for tree menu