Class: AssetLink
- Inherits:
-
ApplicationRecord
- Object
- ActiveRecord::Base
- ApplicationRecord
- AssetLink
- Includes:
- Api::AssetLinkIo::Extensions, Uuid::Uuidable
- Defined in:
- app/models/asset_link.rb
Overview
AssetLink is powered by acts-as-dag Briefly, acts-as-dag attempts to implement a directed-acyclic-graph in a relational database. In order to optimize for retrieval it inserts an AssetLink record for EACH ancestor-descendant link. As a result, it is possible to retrieve ALL ancestors for a given plate in a single query. On the flip side, this makes insert operations more expensive as the graph grows.
As a result, try and avoid adding wells in to asset links, and link between Labware only.
The children,parents,ancestors,descendants methods are all Rails associations, and so can have further scopes applied to them
Defined Under Namespace
Modules: Associations Classes: Job
Class Method Summary collapse
-
.create_edge(ancestor, descendant) ⇒ Boolean
Creates an edge between the ancestor and descendant nodes using save.
-
.save_edge_or_handle_error(edge) ⇒ Boolean
Saves the edge between the ancestor and descendant nodes or handles errors.
-
.unique_validation_error?(edge) ⇒ Boolean
Checks if the validation error includes a specific message indicating a unique link already exists.
-
.unique_violation_error?(edge, exception) ⇒ Boolean
Checks if the unique constraint violation involves the specified columns.
Instance Method Summary collapse
Methods included from Uuid::Uuidable
included, #unsaved_uuid!, #uuid
Methods included from Api::AssetLinkIo::Extensions
Methods inherited from ApplicationRecord
alias_association, convert_labware_to_receptacle_for, find_by_id_or_name, find_by_id_or_name!
Methods included from Squishify
Class Method Details
.create_edge(ancestor, descendant) ⇒ Boolean
Creates an edge between the ancestor and descendant nodes using save.
This method first attempts to find an existing link between the ancestor and descendant. If no link is found, it builds a new edge and saves it. If a link is found, it makes the link an edge and saves it.
This method is overridden to handle race conditions in finding an existing link and has_duplicates validation. It also assumes that there is a unique-together index on ancestor_id and descendant_id columns.
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'app/models/asset_link.rb', line 97 def self.create_edge(ancestor, descendant) # Two processes try to find an existing link. link = find_link(ancestor, descendant) # Either or both may find no link and try to create a new edge. if link.nil? edge = build_edge(ancestor, descendant) result = save_edge_or_handle_error(edge) return result unless result.nil? # Bubble up. # Losing process finds the edge created by the winning process. link = find_link(ancestor, descendant) end return if link.nil? link.make_direct link.changed? ? link.save : true end |
.save_edge_or_handle_error(edge) ⇒ Boolean
Saves the edge between the ancestor and descendant nodes or handles errors.
123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'app/models/asset_link.rb', line 123 def self.save_edge_or_handle_error(edge) # Winning process successfully saves the edge (direct link). return true if edge.save # has_duplicate validation may see it for the losing process before # hitting the DB. return false unless unique_validation_error?(edge) # Bubble up. edge.errors.clear # Clear all errors and use the existing link. rescue ActiveRecord::RecordNotUnique => e # Unique constraint violation is triggered for the losing process after # hitting the DB. raise unless unique_violation_error?(edge, e) # Bubble up. end |
.unique_validation_error?(edge) ⇒ Boolean
Checks if the validation error includes a specific message indicating a unique link already exists.
142 143 144 |
# File 'app/models/asset_link.rb', line 142 def self.unique_validation_error?(edge) edge.errors[:base].include?('Link already exists between these points') end |
.unique_violation_error?(edge, exception) ⇒ Boolean
Checks if the unique constraint violation involves the specified columns.
153 154 155 |
# File 'app/models/asset_link.rb', line 153 def self.unique_violation_error?(edge, exception) [edge.ancestor_id_column_name, edge.descendant_id_column_name].all? { |col| exception..include?(col) } end |
Instance Method Details
#destroy! ⇒ Object
34 35 |
# File 'app/models/asset_link.rb', line 34 def destroy! end |