Module: DagMe::Model
- Extended by:
- ActiveSupport::Concern
- Defined in:
- lib/dag_me/model.rb
Class Method Summary collapse
-
.attach(model, config) ⇒ Object
Builds the per-dag machinery: edge/paths constants and associations.
Instance Method Summary collapse
- #add_child(node, dag: nil) ⇒ Object
- #add_parent(node, dag: nil) ⇒ Object
- #ancestor_of?(node, dag: nil) ⇒ Boolean
- #ancestors(dag: nil) ⇒ Object
- #descendant_of?(node, dag: nil) ⇒ Boolean
- #descendants(dag: nil) ⇒ Object
- #leaf?(dag: nil) ⇒ Boolean
- #remove_child(node, dag: nil) ⇒ Object
- #remove_parent(node, dag: nil) ⇒ Object
- #root?(dag: nil) ⇒ Boolean
- #self_and_ancestors(dag: nil) ⇒ Object
- #self_and_descendants(dag: nil) ⇒ Object
-
#subgraph(dag: nil) ⇒ Object
The induced subgraph rooted here: this node, its descendants, and the edges among them.
- #subgraph_edges(dag: nil) ⇒ Object
Class Method Details
.attach(model, config) ⇒ Object
Builds the per-dag machinery: edge/paths constants and associations. Called by the macro once per dag_me declaration, so a model hosting several named graphs gets one full set each.
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/dag_me/model.rb', line 10 def self.attach(model, config) parent_fk = config.composite_pk? ? config.edge_parent_columns.map(&:to_sym) : :parent_id child_fk = config.composite_pk? ? config.edge_child_columns.map(&:to_sym) : :child_id pk_opt = config.composite_pk? ? { primary_key: config.node_pk_columns.map(&:to_sym) } : {} child_edges = config.association_name('dag_child_edges') parent_edges = config.association_name('dag_parent_edges') edge_class = Class.new(ActiveRecord::Base) model.const_set(config.edge_class_name, edge_class) edge_class.table_name = config.edge_table edge_class.belongs_to :parent, class_name: model.name, foreign_key: parent_fk, inverse_of: child_edges, **pk_opt edge_class.belongs_to :child, class_name: model.name, foreign_key: child_fk, inverse_of: parent_edges, **pk_opt if config.closure? paths_class = Class.new(ActiveRecord::Base) model.const_set(config.paths_class_name, paths_class) paths_class.table_name = config.paths_table paths_class.primary_key = config.paths_ancestor_columns + config.paths_descendant_columns end model.has_many child_edges, class_name: "#{model.name}::#{config.edge_class_name}", foreign_key: parent_fk, inverse_of: :parent, dependent: nil, **pk_opt model.has_many config.association_name('children'), through: child_edges, source: :child model.has_many parent_edges, class_name: "#{model.name}::#{config.edge_class_name}", foreign_key: child_fk, inverse_of: :child, dependent: nil, **pk_opt model.has_many config.association_name('parents'), through: parent_edges, source: :parent end |
Instance Method Details
#add_child(node, dag: nil) ⇒ Object
90 91 92 93 94 |
# File 'lib/dag_me/model.rb', line 90 def add_child(node, dag: nil) config = self.class.dag_config_for(dag) DagMe.translate_errors { config.edge_class.create!(parent: self, child: node) } node end |
#add_parent(node, dag: nil) ⇒ Object
96 97 98 99 100 |
# File 'lib/dag_me/model.rb', line 96 def add_parent(node, dag: nil) config = self.class.dag_config_for(dag) DagMe.translate_errors { config.edge_class.create!(parent: node, child: self) } node end |
#ancestor_of?(node, dag: nil) ⇒ Boolean
134 135 136 |
# File 'lib/dag_me/model.rb', line 134 def ancestor_of?(node, dag: nil) self.class.dag(dag).adapter.reachable?(self, node) end |
#ancestors(dag: nil) ⇒ Object
118 119 120 |
# File 'lib/dag_me/model.rb', line 118 def ancestors(dag: nil) self.class.dag(dag).adapter.ancestors(self) end |
#descendant_of?(node, dag: nil) ⇒ Boolean
138 139 140 |
# File 'lib/dag_me/model.rb', line 138 def descendant_of?(node, dag: nil) self.class.dag(dag).adapter.reachable?(node, self) end |
#descendants(dag: nil) ⇒ Object
122 123 124 |
# File 'lib/dag_me/model.rb', line 122 def descendants(dag: nil) self.class.dag(dag).adapter.descendants(self) end |
#leaf?(dag: nil) ⇒ Boolean
157 158 159 160 |
# File 'lib/dag_me/model.rb', line 157 def leaf?(dag: nil) config = self.class.dag_config_for(dag) !public_send(config.association_name('dag_child_edges')).exists? end |
#remove_child(node, dag: nil) ⇒ Object
102 103 104 105 106 107 108 |
# File 'lib/dag_me/model.rb', line 102 def remove_child(node, dag: nil) config = self.class.dag_config_for(dag) DagMe.translate_errors do config.edge_class.where(dag_edge_key(config, parent: self, child: node)).delete_all end node end |
#remove_parent(node, dag: nil) ⇒ Object
110 111 112 113 114 115 116 |
# File 'lib/dag_me/model.rb', line 110 def remove_parent(node, dag: nil) config = self.class.dag_config_for(dag) DagMe.translate_errors do config.edge_class.where(dag_edge_key(config, parent: node, child: self)).delete_all end node end |
#root?(dag: nil) ⇒ Boolean
152 153 154 155 |
# File 'lib/dag_me/model.rb', line 152 def root?(dag: nil) config = self.class.dag_config_for(dag) !public_send(config.association_name('dag_parent_edges')).exists? end |
#self_and_ancestors(dag: nil) ⇒ Object
126 127 128 |
# File 'lib/dag_me/model.rb', line 126 def self_and_ancestors(dag: nil) self.class.dag(dag).adapter.self_and_ancestors(self) end |
#self_and_descendants(dag: nil) ⇒ Object
130 131 132 |
# File 'lib/dag_me/model.rb', line 130 def self_and_descendants(dag: nil) self.class.dag(dag).adapter.self_and_descendants(self) end |
#subgraph(dag: nil) ⇒ Object
The induced subgraph rooted here: this node, its descendants, and the edges among them.
144 145 146 |
# File 'lib/dag_me/model.rb', line 144 def subgraph(dag: nil) self_and_descendants(dag:) end |
#subgraph_edges(dag: nil) ⇒ Object
148 149 150 |
# File 'lib/dag_me/model.rb', line 148 def subgraph_edges(dag: nil) self.class.dag(dag).edges_among(self_and_descendants(dag:)) end |