Class: Neo4j::ActiveNode::Query::QueryProxy
- Inherits:
-
Object
- Object
- Neo4j::ActiveNode::Query::QueryProxy
- Includes:
- Dependent::QueryProxyMethods, QueryProxyEagerLoading, QueryProxyEnumerable, QueryProxyFindInBatches, QueryProxyMethods, QueryProxyMethodsOfMassUpdating
- Defined in:
- lib/neo4j/active_node/query/query_proxy.rb,
lib/neo4j/active_node/query/query_proxy_link.rb
Defined Under Namespace
Classes: Link
Constant Summary collapse
- METHODS =
%w(where where_not rel_where rel_order order skip limit)
Constants included from QueryProxyMethods
Neo4j::ActiveNode::Query::QueryProxyMethods::FIRST, Neo4j::ActiveNode::Query::QueryProxyMethods::LAST
Instance Attribute Summary collapse
-
#association ⇒ Object
readonly
The most recent node to start a QueryProxy chain.
-
#context ⇒ Object
readonly
Returns the value of attribute context.
-
#model ⇒ Object
readonly
The most recent node to start a QueryProxy chain.
-
#node_var ⇒ Object
readonly
The current node identifier on deck, so to speak.
-
#query_proxy ⇒ Object
readonly
Returns the value of attribute query_proxy.
-
#rel_var ⇒ Object
readonly
The relationship identifier most recently used by the QueryProxy chain.
-
#source_object ⇒ Object
readonly
The most recent node to start a QueryProxy chain.
-
#start_object ⇒ Object
readonly
Returns the value of attribute start_object.
-
#starting_query ⇒ Object
readonly
The most recent node to start a QueryProxy chain.
Instance Method Summary collapse
-
#<<(other_node) ⇒ Object
To add a relationship for the node for the association on this QueryProxy.
- #[](index) ⇒ Object
- #_create_relationship(other_node_or_nodes, properties) ⇒ Object
-
#_model_label_string(with_labels = true) ⇒ Object
param [TrueClass, FalseClass] with_labels This param is used by certain QueryProxy methods that already have the neo_id and therefore do not need labels.
- #_nodeify!(*args) ⇒ Object
- #base_query(var, with_labels = true) ⇒ Object
-
#branch { ... } ⇒ QueryProxy
Executes the relation chain specified in the block, while keeping the current scope.
- #create(other_nodes, properties = {}) ⇒ Object
- #identity ⇒ Object (also: #node_identity)
-
#initialize(model, association = nil, options = {}) ⇒ QueryProxy
constructor
QueryProxy is ActiveNode’s Cypher DSL.
- #inspect ⇒ Object
-
#method_missing(method_name, *args, &block) ⇒ Object
QueryProxy objects act as a representation of a model at the class level so we pass through calls This allows us to define class functions for reusable query chaining or for end-of-query aggregation/summarizing.
- #new_link(node_var = nil) ⇒ Object
- #optional? ⇒ Boolean
- #params(params) ⇒ Object
-
#query ⇒ Object
Like calling #query_as, but for when you don’t care about the variable name.
-
#query_as(var, with_labels = true) ⇒ Object
Build a Neo4j::Core::Query object for the QueryProxy.
- #read_attribute_for_serialization(*args) ⇒ Object
- #rel_identity ⇒ Object
- #respond_to_missing?(method_name, include_all = false) ⇒ Boolean
-
#scoping ⇒ Object
Scope all queries to the current scope.
-
#to_cypher_with_params(columns = [self.identity]) ⇒ String
Returns a string of the cypher query with return objects and params.
Methods included from Dependent::QueryProxyMethods
#each_for_destruction, #unique_nodes
Methods included from QueryProxyEagerLoading
#each, #with_associations, #with_associations_spec
Methods included from QueryProxyFindInBatches
Methods included from QueryProxyMethodsOfMassUpdating
#delete, #delete_all, #delete_all_rels, #destroy, #replace_with, #update_all, #update_all_rels
Methods included from QueryProxyMethods
#as_models, #count, #empty?, #exists?, #find, #find_or_create_by, #first, #first_rel_to, #include?, #last, #limit_value, #match_to, #optional, #order_property, #rel, #rels, #rels_to, #size
Methods included from QueryProxyEnumerable
#==, #each, #each_rel, #each_with_rel, #fetch_result_cache, #pluck, #result, #result_cache?, #result_cache_for
Constructor Details
#initialize(model, association = nil, options = {}) ⇒ QueryProxy
QueryProxy is ActiveNode’s Cypher DSL. While the name might imply that it creates queries in a general sense, it is actually referring to Neo4j::Core::Query, which is a pure Ruby Cypher DSL provided by the neo4j-core gem. QueryProxy provides ActiveRecord-like methods for common patterns. When it’s not handling CRUD for relationships and queries, it provides ActiveNode’s association chaining (‘student.lessons.teachers.where(age: 30).hobbies`) and enjoys long walks on the beach.
It should not ever be necessary to instantiate a new QueryProxy object directly, it always happens as a result of calling a method that makes use of it.
originated. has_many) that created this object. QueryProxy objects are evaluated lazily.
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/neo4j/active_node/query/query_proxy.rb', line 39 def initialize(model, association = nil, = {}) @model = model @association = association @context = .delete(:context) = @associations_spec = [] () @match_type = @optional ? :optional_match : :match @rel_var = [:rel] || _rel_chain_var @chain = [] @params = @query_proxy ? @query_proxy.instance_variable_get('@params') : {} end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method_name, *args, &block) ⇒ Object
QueryProxy objects act as a representation of a model at the class level so we pass through calls This allows us to define class functions for reusable query chaining or for end-of-query aggregation/summarizing
245 246 247 248 249 250 251 |
# File 'lib/neo4j/active_node/query/query_proxy.rb', line 245 def method_missing(method_name, *args, &block) if @model && @model.respond_to?(method_name) scoping { @model.public_send(method_name, *args, &block) } else super end end |
Instance Attribute Details
#association ⇒ Object (readonly)
The most recent node to start a QueryProxy chain. Will be nil when using QueryProxy chains on class methods.
14 15 16 |
# File 'lib/neo4j/active_node/query/query_proxy.rb', line 14 def association @association end |
#context ⇒ Object
Returns the value of attribute context.
261 262 263 |
# File 'lib/neo4j/active_node/query/query_proxy.rb', line 261 def context @context end |
#model ⇒ Object (readonly)
The most recent node to start a QueryProxy chain. Will be nil when using QueryProxy chains on class methods.
14 15 16 |
# File 'lib/neo4j/active_node/query/query_proxy.rb', line 14 def model @model end |
#node_var ⇒ Object (readonly)
The current node identifier on deck, so to speak. It is the object that will be returned by calling each and the last node link in the QueryProxy chain.
64 65 66 |
# File 'lib/neo4j/active_node/query/query_proxy.rb', line 64 def node_var @node_var end |
#query_proxy ⇒ Object (readonly)
Returns the value of attribute query_proxy.
60 61 62 |
# File 'lib/neo4j/active_node/query/query_proxy.rb', line 60 def query_proxy @query_proxy end |
#rel_var ⇒ Object (readonly)
The relationship identifier most recently used by the QueryProxy chain.
71 72 73 |
# File 'lib/neo4j/active_node/query/query_proxy.rb', line 71 def rel_var @rel_var end |
#source_object ⇒ Object (readonly)
The most recent node to start a QueryProxy chain. Will be nil when using QueryProxy chains on class methods.
14 15 16 |
# File 'lib/neo4j/active_node/query/query_proxy.rb', line 14 def source_object @source_object end |
#start_object ⇒ Object (readonly)
Returns the value of attribute start_object.
60 61 62 |
# File 'lib/neo4j/active_node/query/query_proxy.rb', line 60 def start_object @start_object end |
#starting_query ⇒ Object (readonly)
The most recent node to start a QueryProxy chain. Will be nil when using QueryProxy chains on class methods.
14 15 16 |
# File 'lib/neo4j/active_node/query/query_proxy.rb', line 14 def starting_query @starting_query end |
Instance Method Details
#<<(other_node) ⇒ Object
To add a relationship for the node for the association on this QueryProxy
166 167 168 169 170 171 172 173 174 175 |
# File 'lib/neo4j/active_node/query/query_proxy.rb', line 166 def <<(other_node) if @start_object._persisted_obj create(other_node, {}) elsif @association @start_object.defer_create(@association.name, other_node) else fail 'Another crazy error!' end self end |
#[](index) ⇒ Object
196 197 198 199 200 |
# File 'lib/neo4j/active_node/query/query_proxy.rb', line 196 def [](index) # TODO: Maybe for this and other methods, use array if already loaded, otherwise # use OFFSET and LIMIT 1? self.to_a[index] end |
#_create_relationship(other_node_or_nodes, properties) ⇒ Object
233 234 235 |
# File 'lib/neo4j/active_node/query/query_proxy.rb', line 233 def _create_relationship(other_node_or_nodes, properties) association._create_relationship(@start_object, other_node_or_nodes, properties) end |
#_model_label_string(with_labels = true) ⇒ Object
param [TrueClass, FalseClass] with_labels This param is used by certain QueryProxy methods that already have the neo_id and therefore do not need labels. The @association_labels instance var is set during init and used during association chaining to keep labels out of Cypher queries.
117 118 119 120 |
# File 'lib/neo4j/active_node/query/query_proxy.rb', line 117 def _model_label_string(with_labels = true) return if !@model || (!with_labels || @association_labels == false) @model.mapped_label_names.map { |label_name| ":`#{label_name}`" }.join end |
#_nodeify!(*args) ⇒ Object
221 222 223 224 225 226 227 228 229 230 231 |
# File 'lib/neo4j/active_node/query/query_proxy.rb', line 221 def _nodeify!(*args) other_nodes = [args].flatten!.map! do |arg| (arg.is_a?(Integer) || arg.is_a?(String)) ? @model.find_by(id: arg) : arg end.compact if @model && other_nodes.any? { |other_node| !other_node.class.mapped_label_names.include?(@model.mapped_label_name) } fail ArgumentError, "Node must be of the association's class when model is specified" end other_nodes end |
#base_query(var, with_labels = true) ⇒ Object
104 105 106 107 108 109 110 111 112 |
# File 'lib/neo4j/active_node/query/query_proxy.rb', line 104 def base_query(var, with_labels = true) if @association chain_var = _association_chain_var (_association_query_start(chain_var) & _query).break.send(@match_type, "(#{chain_var})#{_association_arrow}(#{var}#{_model_label_string})") else starting_query ? starting_query : _query_model_as(var, with_labels) end end |
#branch { ... } ⇒ QueryProxy
Executes the relation chain specified in the block, while keeping the current scope
188 189 190 191 192 193 194 |
# File 'lib/neo4j/active_node/query/query_proxy.rb', line 188 def branch(&block) if block instance_eval(&block).query.proxy_as(self.model, identity) else fail LocalJumpError, 'no block given' end end |
#create(other_nodes, properties = {}) ⇒ Object
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 |
# File 'lib/neo4j/active_node/query/query_proxy.rb', line 202 def create(other_nodes, properties = {}) fail 'Can only create relationships on associations' if !@association other_nodes = _nodeify!(*other_nodes) Neo4j::Transaction.run do other_nodes.each do |other_node| other_node.save unless other_node.neo_id return false if @association.perform_callback(@start_object, other_node, :before) == false @start_object.association_proxy_cache.clear _create_relationship(other_node, properties) @association.perform_callback(@start_object, other_node, :after) end end end |
#identity ⇒ Object Also known as: node_identity
65 66 67 |
# File 'lib/neo4j/active_node/query/query_proxy.rb', line 65 def identity @node_var || _result_string end |
#inspect ⇒ Object
56 57 58 |
# File 'lib/neo4j/active_node/query/query_proxy.rb', line 56 def inspect "#<QueryProxy #{@context} CYPHER: #{self.to_cypher.inspect}>" end |
#new_link(node_var = nil) ⇒ Object
263 264 265 266 267 268 |
# File 'lib/neo4j/active_node/query/query_proxy.rb', line 263 def new_link(node_var = nil) self.clone.tap do |new_query_proxy| new_query_proxy.instance_variable_set('@result_cache', nil) new_query_proxy.instance_variable_set('@node_var', node_var) if node_var end end |
#optional? ⇒ Boolean
257 258 259 |
# File 'lib/neo4j/active_node/query/query_proxy.rb', line 257 def optional? @optional == true end |
#params(params) ⇒ Object
78 79 80 |
# File 'lib/neo4j/active_node/query/query_proxy.rb', line 78 def params(params) new_link.tap { |new_query| new_query._add_params(params) } end |
#query ⇒ Object
Like calling #query_as, but for when you don’t care about the variable name
83 84 85 |
# File 'lib/neo4j/active_node/query/query_proxy.rb', line 83 def query query_as(identity) end |
#query_as(var, with_labels = true) ⇒ Object
Build a Neo4j::Core::Query object for the QueryProxy. This is necessary when you want to take an existing QueryProxy chain and work with it from the more powerful (but less friendly) Neo4j::Core::Query.
- .. code-block
-
ruby
student.lessons.query_as(:l).with('your cypher here...')
94 95 96 97 98 99 100 101 102 |
# File 'lib/neo4j/active_node/query/query_proxy.rb', line 94 def query_as(var, with_labels = true) result_query = @chain.inject(base_query(var, with_labels).params(@params)) do |query, link| args = link.args(var, rel_var) args.is_a?(Array) ? query.send(link.clause, *args) : query.send(link.clause, args) end result_query.tap { |query| query.proxy_chain_level = _chain_level } end |
#read_attribute_for_serialization(*args) ⇒ Object
237 238 239 |
# File 'lib/neo4j/active_node/query/query_proxy.rb', line 237 def read_attribute_for_serialization(*args) to_a.map { |o| o.read_attribute_for_serialization(*args) } end |
#rel_identity ⇒ Object
72 73 74 75 76 |
# File 'lib/neo4j/active_node/query/query_proxy.rb', line 72 def rel_identity ActiveSupport::Deprecation.warn 'rel_identity is deprecated and may be removed from future releases, use rel_var instead.', caller @rel_var end |
#respond_to_missing?(method_name, include_all = false) ⇒ Boolean
253 254 255 |
# File 'lib/neo4j/active_node/query/query_proxy.rb', line 253 def respond_to_missing?(method_name, include_all = false) (@model && @model.respond_to?(method_name, include_all)) || super end |
#scoping ⇒ Object
Scope all queries to the current scope.
- .. code-block
-
ruby
Comment.where(post_id: 1).scoping do
Comment.first
end
TODO: unscoped Please check unscoped if you want to remove all previous scopes (including the default_scope) during the execution of a block.
133 134 135 136 137 138 139 |
# File 'lib/neo4j/active_node/query/query_proxy.rb', line 133 def scoping previous = @model.current_scope @model.current_scope = self yield ensure @model.current_scope = previous end |
#to_cypher_with_params(columns = [self.identity]) ⇒ String
Returns a string of the cypher query with return objects and params
160 161 162 163 |
# File 'lib/neo4j/active_node/query/query_proxy.rb', line 160 def to_cypher_with_params(columns = [self.identity]) final_query = query.return_query(columns) "#{final_query.to_cypher} | params: #{final_query.send(:merge_params)}" end |