在数据库中存储树

时间:2014-07-21 18:54:02

标签: ruby-on-rails database tree persistent-storage

我有一个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

1 个答案:

答案 0 :(得分:0)

虽然自己尝试并实现所有这些逻辑是好的(为了学习),但我更喜欢使用gem来实现这种功能。有多种选择。我个人使用ancestory gemhttps://github.com/stefankroes/ancestry)来表示这种应用。我觉得这个宝石似乎不能与Rails 4一起使用,但是如上所述:Does The Ancestry Gem Work With Rails 4?

您可以在此SO问题/答案中找到更多选项:acts_as_tree vs ancestry gem for tree menu