class ActiveGraph::Relationship::Persistence::QueryFactory
This class builds and executes a Cypher query, using information from the graph objects to determine
whether they need to be created simultaneously. It keeps the rel instance from being responsible for inspecting the nodes or talking with Shared::QueryFactory.
Constants
- NODE_SYMBOLS
Attributes
Public Class Methods
# File lib/active_graph/relationship/persistence/query_factory.rb 9 def initialize(from_node, to_node, rel) 10 @from_node = from_node 11 @to_node = to_node 12 @rel = rel 13 end
Public Instance Methods
TODO: This feels like it should also wrap the rel, but that is handled in ActiveGraph::Relationship::Persistence
at the moment. Builds and executes the query using the objects giving during init. It holds the process:
-
Execute node callbacks if needed
-
Create and execute the query
-
Mix the query response into the unpersisted objects given during init
# File lib/active_graph/relationship/persistence/query_factory.rb 21 def build! 22 node_before_callbacks! do 23 res = query_factory(rel, rel_id, iterative_query).query.unwrapped.return(*unpersisted_return_ids).first 24 node_symbols.each { |n| wrap!(send(n), res, n) } 25 @unwrapped_rel = res[rel_id] 26 end 27 end
Private Instance Methods
Each node must be either created or matched before the relationship can be created. This class does not know or care about
how that happens, it just knows that it needs a usable ActiveGraph::Core::Query object to do that.
This method is “iterative” because it creates one factory for each node but the second builds upon the first.
# File lib/active_graph/relationship/persistence/query_factory.rb 57 def iterative_query 58 node_symbols.inject(false) do |iterative_query, sym| 59 obj = send(sym) 60 query_factory(obj, sym, iterative_query) 61 end 62 end
Node
callbacks only need to be executed if the node is not persisted. We let the `conditional_callback` method do the work,
we only have to give it the type of callback we expect to be run and the condition which, if true, will prevent it from executing.
# File lib/active_graph/relationship/persistence/query_factory.rb 37 def node_before_callbacks! 38 validate_unpersisted_nodes! 39 from_node.conditional_callback(:create, from_node.persisted?) do 40 to_node.conditional_callback(:create, to_node.persisted?) do 41 yield 42 end 43 end 44 end
# File lib/active_graph/relationship/persistence/query_factory.rb 91 def node_symbols 92 self.class::NODE_SYMBOLS 93 end
Isolates the dependency to the shared class. This has an awareness of ActiveGraph::Core::Query
and will match or create
based on the current state of the object passed in.
# File lib/active_graph/relationship/persistence/query_factory.rb 66 def query_factory(obj, sym, factory = false) 67 ActiveGraph::Shared::QueryFactory.create(obj, sym).tap do |factory_instance| 68 factory_instance.base_query = factory.blank? ? false : factory.query 69 end 70 end
# File lib/active_graph/relationship/persistence/query_factory.rb 31 def rel_id 32 @rel_id ||= rel.rel_identifier 33 end
@return [Array<Symbol>] The Cypher identifiers that will be returned from the query. We only need to return objects from our query that were created during it, otherwise we impact performance.
# File lib/active_graph/relationship/persistence/query_factory.rb 74 def unpersisted_return_ids 75 [rel_id].tap do |result| 76 node_symbols.each { |k| result << k unless send(k).persisted? } 77 end 78 end
# File lib/active_graph/relationship/persistence/query_factory.rb 46 def validate_unpersisted_nodes! 47 node_symbols.each do |s| 48 obj = send(s) 49 next if obj.persisted? 50 fail RelCreateFailedError, "Cannot create rel with unpersisted, invalid #{s}" unless obj.valid? 51 end 52 end
@param [ActiveGraph::Node] node A node, persisted or unpersisted @param [Struct] res The result of calling `return` on a ActiveGraph::Core::Query
object. It responds to the same keys
as our graph objects. If the object is unpersisted and was created during the query, the unwrapped node is mixed in, making the object reflect as "persisted".
@param [Symbol] key :from_node or :to_node, the object to request from the response.
# File lib/active_graph/relationship/persistence/query_factory.rb 85 def wrap!(node, res, key) 86 return if node.persisted? || !res.keys.include?(key) 87 unwrapped = res[key] 88 node.init_on_load(unwrapped, unwrapped.properties) 89 end