Module: Ancestry::MaterializedPath2

Includes:
MaterializedPath
Defined in:
lib/ancestry/materialized_path2.rb

Overview

store ancestry as /grandparent_id/parent_id/ root: a=/,id=1 children=#a#id/% == /1/% 3: a=/1/2/,id=3 children=#a#id/% == /1/2/3/%

Defined Under Namespace

Modules: InstanceMethods

Class Method Summary collapse

Instance Method Summary collapse

Methods included from MaterializedPath

#ancestors_of, #ancestry_depth_change, #children_of, #concat, concat, #descendant_before_last_save_conditions, #descendant_conditions, #descendants_of, #inpath_of, #ordered_by_ancestry_and, parse, #parse_ancestry_column, #path_of, #roots, #siblings_of, #subtree_of

Class Method Details

.child_ancestry_sql(table_name, ancestry_column, primary_key, delimiter, adapter) ⇒ Object



56
57
58
# File 'lib/ancestry/materialized_path2.rb', line 56

def self.child_ancestry_sql(table_name, ancestry_column, primary_key, delimiter, adapter)
  MaterializedPath.concat(adapter, "#{table_name}.#{ancestry_column}", "#{table_name}.#{primary_key}", "'#{delimiter}'")
end

.child_ancestry_value(ancestry_value, id, delimiter) ⇒ Object



52
53
54
# File 'lib/ancestry/materialized_path2.rb', line 52

def self.child_ancestry_value(ancestry_value, id, delimiter)
  "#{ancestry_value}#{id}#{delimiter}"
end

.construct_depth_sql(table_name, ancestry_column, ancestry_delimiter) ⇒ Object

module method



71
72
73
74
75
# File 'lib/ancestry/materialized_path2.rb', line 71

def self.construct_depth_sql(table_name, ancestry_column, ancestry_delimiter)
  tmp = %{(LENGTH(#{table_name}.#{ancestry_column}) - LENGTH(REPLACE(#{table_name}.#{ancestry_column},'#{ancestry_delimiter}','')))}
  tmp += "/#{ancestry_delimiter.size}" if ancestry_delimiter.size > 1
  "(#{tmp} -1)"
end

.descendants_condition(attr, child_ancestry, _delimiter) ⇒ Object

mp2: descendants just use LIKE (trailing delimiter prevents false prefix matches)



61
62
63
# File 'lib/ancestry/materialized_path2.rb', line 61

def self.descendants_condition(attr, child_ancestry, _delimiter)
  attr.matches("#{child_ancestry}%", nil, true)
end

.extended(base) ⇒ Object



10
11
12
13
# File 'lib/ancestry/materialized_path2.rb', line 10

def self.extended(base)
  base.send(:include, MaterializedPath::InstanceMethods)
  base.send(:include, InstanceMethods)
end

.generate(ancestor_ids, delimiter, root) ⇒ Object



44
45
46
47
48
49
50
# File 'lib/ancestry/materialized_path2.rb', line 44

def self.generate(ancestor_ids, delimiter, root)
  if ancestor_ids.present? && ancestor_ids.any?
    "#{delimiter}#{ancestor_ids.join(delimiter)}#{delimiter}"
  else
    root
  end
end

.indirects_condition(attr, child_ancestry, delimiter) ⇒ Object

mp2: indirects match child_ancestry + at least one more segment



66
67
68
# File 'lib/ancestry/materialized_path2.rb', line 66

def self.indirects_condition(attr, child_ancestry, delimiter)
  attr.matches("#{child_ancestry}%#{delimiter}%", nil, true)
end

.validation_options(primary_key_format, delimiter) ⇒ Object



77
78
79
80
81
82
# File 'lib/ancestry/materialized_path2.rb', line 77

def self.validation_options(primary_key_format, delimiter)
  {
    format: {with: /\A#{Regexp.escape(delimiter)}(#{primary_key_format}#{Regexp.escape(delimiter)})*\z/.freeze},
    allow_nil: false
  }
end

Instance Method Details

#ancestry_depth_sqlObject



36
37
38
# File 'lib/ancestry/materialized_path2.rb', line 36

def ancestry_depth_sql
  @ancestry_depth_sql ||= MaterializedPath2.construct_depth_sql(table_name, ancestry_column, ancestry_delimiter)
end

#ancestry_rootObject



28
29
30
# File 'lib/ancestry/materialized_path2.rb', line 28

def ancestry_root
  ancestry_delimiter
end

#child_ancestry_sqlObject



32
33
34
# File 'lib/ancestry/materialized_path2.rb', line 32

def child_ancestry_sql
  MaterializedPath2.child_ancestry_sql(table_name, ancestry_column, primary_key, ancestry_delimiter, connection.adapter_name.downcase)
end

#descendants_by_ancestry(ancestry) ⇒ Object



24
25
26
# File 'lib/ancestry/materialized_path2.rb', line 24

def descendants_by_ancestry(ancestry)
  MaterializedPath2.descendants_condition(arel_table[ancestry_column], ancestry, ancestry_delimiter)
end

#generate_ancestry(ancestor_ids) ⇒ Object



40
41
42
# File 'lib/ancestry/materialized_path2.rb', line 40

def generate_ancestry(ancestor_ids)
  MaterializedPath2.generate(ancestor_ids, ancestry_delimiter, ancestry_root)
end

#indirects_of(object) ⇒ Object



15
16
17
18
# File 'lib/ancestry/materialized_path2.rb', line 15

def indirects_of(object)
  node = to_node(object)
  where(MaterializedPath2.indirects_condition(arel_table[ancestry_column], node.child_ancestry, ancestry_delimiter))
end

#ordered_by_ancestry(order = nil) ⇒ Object



20
21
22
# File 'lib/ancestry/materialized_path2.rb', line 20

def ordered_by_ancestry(order = nil)
  reorder(Arel::Nodes::Ascending.new(arel_table[ancestry_column]), order)
end