0

I have a rails app where one of my resources is called "organizations" and organizations can have an arbitrary number of sub-organizations. The manage this, in the database I have a parent id for each organization entry.

Right now, I have a method in my organization model that looks like this to build all of the organization trees:

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 testing this in the console it does what I want. So far, so good. However, now to actually use this thing I have created I want to put it somewhere so that it's at least somewhat useful. This could mean two things:

Okay:

Put this into an instance variable by making a call to after_initialize(). I tried this and cannot get it to work as it always returns nil:

class Organization < ActiveRecord::Base
  after_initialize :set_tree

  @trees = nil
  def set_tree
    @trees = self.build_org_trees_wrapper
  end

AWESOME

Somehow store this puppy in sessions variable, cache, or key value store so that I can always have access to it. I would also love some advice on how to do this if it is possible.

I am also in a little over my head here so I welcome any criticism on my approach whatsoever.

Edit(forgot my node class):

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
ohhh
  • 972
  • 9
  • 24

1 Answers1

0

While it is good to try and implement all this logic by yourself (in order to learn), but I would prefer using a gem for this kind of functionality. There are multiple options available. I personally use ancestory gem(https://github.com/stefankroes/ancestry) for this kind of application. It my seem that this gem doesn't work with Rails 4, but it does, as mentioned here: Does The Ancestry Gem Work With Rails 4?.

You can find more options in this SO question/answer: acts_as_tree vs ancestry gem for tree menu

Community
  • 1
  • 1
San
  • 1,954
  • 1
  • 14
  • 18
  • I would prefer not use a gem at this point because all of the methods that I've written for this have been working fine from the console, so the only thing really left to do is to somehow persist the information. I only included the tree-building method to give people a better idea of how the data was being stored. – ohhh Jul 21 '14 at 19:47