Module: Ancestry::MaterializedPath2
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
-
.child_ancestry_sql(table_name, ancestry_column, primary_key, delimiter, adapter) ⇒ Object
-
.child_ancestry_value(ancestry_value, id, delimiter) ⇒ Object
-
.construct_depth_sql(table_name, ancestry_column, ancestry_delimiter) ⇒ Object
-
.descendants_condition(attr, child_ancestry, _delimiter) ⇒ Object
mp2: descendants just use LIKE (trailing delimiter prevents false prefix matches).
-
.extended(base) ⇒ Object
-
.generate(ancestor_ids, delimiter, root) ⇒ Object
-
.indirects_condition(attr, child_ancestry, delimiter) ⇒ Object
mp2: indirects match child_ancestry + at least one more segment.
-
.validation_options(primary_key_format, delimiter) ⇒ Object
Instance Method Summary
collapse
#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
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_sql ⇒ Object
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_root ⇒ Object
28
29
30
|
# File 'lib/ancestry/materialized_path2.rb', line 28
def ancestry_root
ancestry_delimiter
end
|
#child_ancestry_sql ⇒ Object
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
|