Module: ClosureTree::Finders

Extended by:
ActiveSupport::Concern
Defined in:
lib/closure_tree/finders.rb

Instance Method Summary collapse

Instance Method Details

#find_all_by_generation(generation_level) ⇒ Object



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/closure_tree/finders.rb', line 39

def find_all_by_generation(generation_level)
  hierarchy_table = self.class.hierarchy_class.arel_table
  model_table = self.class.arel_table

  # Build the subquery
  descendants_subquery = hierarchy_table
                         .project(hierarchy_table[:descendant_id])
                         .where(hierarchy_table[:ancestor_id].eq(id))
                         .group(hierarchy_table[:descendant_id])
                         .having(hierarchy_table[:generations].maximum.eq(generation_level.to_i))
                         .as('descendants')

  # Build the join
  join_source = model_table
                .join(descendants_subquery)
                .on(model_table[_ct.base_class.primary_key].eq(descendants_subquery[:descendant_id]))
                .join_sources

  s = _ct.base_class.joins(join_source)
  _ct.scope_with_order(s)
end

#find_by_path(path, attributes = {}) ⇒ Object

Find a descendant node whose ancestry_path will be “‘self.ancestry_path + path“`



8
9
10
11
12
# File 'lib/closure_tree/finders.rb', line 8

def find_by_path(path, attributes = {})
  return self if path.empty?

  self.class.find_by_path(path, attributes, id)
end

#find_or_create_by_path(path, attributes = {}) ⇒ Object

Find or create a descendant node whose ancestry_path will be “‘self.ancestry_path + path“`



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/closure_tree/finders.rb', line 15

def find_or_create_by_path(path, attributes = {})
  subpath = _ct.build_ancestry_attr_path(path, attributes)
  return self if subpath.empty?

  found = find_by_path(subpath, attributes)
  return found if found

  attrs = subpath.shift
  _ct.with_advisory_lock do
    # shenanigans because children.create is bound to the superclass
    # (in the case of polymorphism):
    child = children.where(attrs).first || begin
      # Support STI creation by using base_class:
      _ct.create(self.class, attrs).tap do |ea|
        # We know that there isn't a cycle, because we just created it, and
        # cycle detection is expensive when the node is deep.
        ea._ct_skip_cycle_detection!
        children << ea
      end
    end
    child.find_or_create_by_path(subpath, attributes)
  end
end

#without_self(scope) ⇒ Object



61
62
63
# File 'lib/closure_tree/finders.rb', line 61

def without_self(scope)
  scope.without_instance(self)
end