Module: ClosureTree::HashTree::ClassMethods

Defined in:
lib/closure_tree/hash_tree.rb

Instance Method Summary collapse

Instance Method Details

#build_hash_tree(tree_scope) ⇒ Object

Builds nested hash structure using the scope returned from the passed in scope


43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/closure_tree/hash_tree.rb', line 43

def build_hash_tree(tree_scope)
  tree = ActiveSupport::OrderedHash.new
  id_to_hash = {}

  tree_scope.each do |ea|
    h = id_to_hash[ea.id] = ActiveSupport::OrderedHash.new
    if ea.root? || tree.empty? # We're at the top of the tree.
      tree[ea] = h
    else
      id_to_hash[ea._ct_parent_id][ea] = h
    end
  end
  tree
end

#hash_tree(options = {}) ⇒ Object

There is no default depth limit. This might be crazy-big, depending on your tree shape. Hash huge trees at your own peril!


22
23
24
# File 'lib/closure_tree/hash_tree.rb', line 22

def hash_tree(options = {})
  build_hash_tree(hash_tree_scope(options[:limit_depth]))
end

#hash_tree_scope(limit_depth = nil) ⇒ Object


26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/closure_tree/hash_tree.rb', line 26

def hash_tree_scope(limit_depth = nil)
  # Deepest generation, within limit, for each descendant
  # NOTE: Postgres requires HAVING clauses to always contains aggregate functions (!!)
  having_clause = limit_depth ? "HAVING MAX(generations) <= #{limit_depth - 1}" : ''
  generation_depth = <<-SQL.strip_heredoc
    INNER JOIN (
      SELECT descendant_id, MAX(generations) as depth
      FROM #{_ct.quoted_hierarchy_table_name}
      GROUP BY descendant_id
      #{having_clause}
    ) AS generation_depth
      ON #{_ct.quoted_table_name}.#{primary_key} = generation_depth.descendant_id
  SQL
  _ct.scope_with_order(joins(generation_depth), "generation_depth.depth")
end