Module: ActiveGraph::Node::Query::QueryProxyMethods

Included in:
QueryProxy
Defined in:
lib/active_graph/node/query/query_proxy_methods.rb

Overview

rubocop:disable Metrics/ModuleLength

Constant Summary collapse

FIRST =

rubocop:enable Metrics/ModuleLength

'HEAD'
LAST =
'LAST'

Instance Method Summary collapse

Instance Method Details

#as(node_var) ⇒ Object


20
21
22
# File 'lib/active_graph/node/query/query_proxy_methods.rb', line 20

def as(node_var)
  new_link(node_var)
end

#as_models(models) ⇒ Object

Takes an Array of Node models and applies the appropriate WHERE clause So for a `Teacher` model inheriting from a `Person` model and an `Article` model if you called .as_models([Teacher, Article]) The where clause would look something like:

.. code-block

cypher

WHERE (node_var:Teacher:Person OR node_var:Article)

184
185
186
187
188
189
190
191
192
# File 'lib/active_graph/node/query/query_proxy_methods.rb', line 184

def as_models(models)
  where_clause = models.map do |model|
    "`#{identity}`:" + model.mapped_label_names.map do |mapped_label_name|
      "`#{mapped_label_name}`"
    end.join(':')
  end.join(' OR ')

  where("(#{where_clause})")
end

#count(distinct = nil, target = nil) ⇒ Integer

Returns number of nodes of this class.

Returns:

  • (Integer)

    number of nodes of this class


55
56
57
58
59
60
61
62
63
# File 'lib/active_graph/node/query/query_proxy_methods.rb', line 55

def count(distinct = nil, target = nil)
  return 0 if unpersisted_start_object?
  fail(ActiveGraph::InvalidParameterError, ':count accepts the `:distinct` symbol or nil as a parameter') unless distinct.nil? || distinct == :distinct
  query_with_target(target) do |var|
    q = ensure_distinct(var, !distinct.nil?)
    limited_query = self.query.clause?(:limit) ? self.query.break.with(var) : self.query.reorder
    limited_query.pluck("count(#{q}) AS #{var}").first
  end
end

#distinctObject


44
45
46
47
48
# File 'lib/active_graph/node/query/query_proxy_methods.rb', line 44

def distinct
  new_link.tap do |e|
    e.instance_variable_set(:@distinct, true)
  end
end

#empty?(target = nil) ⇒ Boolean Also known as: blank?

Returns:


78
79
80
81
# File 'lib/active_graph/node/query/query_proxy_methods.rb', line 78

def empty?(target = nil)
  return true if unpersisted_start_object?
  query_with_target(target) { |var| !self.exists?(nil, var) }
end

#exists?(node_condition = nil, target = nil) ⇒ Boolean

Returns:


101
102
103
104
105
106
107
108
109
110
# File 'lib/active_graph/node/query/query_proxy_methods.rb', line 101

def exists?(node_condition = nil, target = nil)
  unless [Integer, String, Hash, NilClass].any? { |c| node_condition.is_a?(c) }
    fail(ActiveGraph::InvalidParameterError, ':exists? only accepts ids or conditions')
  end
  query_with_target(target) do |var|
    start_q = exists_query_start(node_condition, var)
    result = start_q.query.reorder.return("ID(#{var}) AS proof_of_life LIMIT 1").first
    !!result
  end
end

#find(*args) ⇒ Object

Give ability to call `#find` on associations to get a scoped find Doesn't pass through via `method_missing` because Enumerable has a `#find` method


26
27
28
# File 'lib/active_graph/node/query/query_proxy_methods.rb', line 26

def find(*args)
  scoping { @model.find(*args) }
end

#find_or_create_by(params) ⇒ Object

When called, this method returns a single node that satisfies the match specified in the params hash. If no existing node is found to satisfy the match, one is created or associated as expected.


152
153
154
155
156
157
158
159
160
161
# File 'lib/active_graph/node/query/query_proxy_methods.rb', line 152

def find_or_create_by(params)
  fail 'Method invalid when called on Class objects' unless source_object
  result = self.where(params).first
  return result unless result.nil?
  ActiveGraph::Base.transaction do
    node = model.create(params)
    self << node
    node
  end
end

#find_or_initialize_by(attributes, &block) ⇒ Object


163
164
165
# File 'lib/active_graph/node/query/query_proxy_methods.rb', line 163

def find_or_initialize_by(attributes, &block)
  find_by(attributes) || initialize_by_current_chain_params(attributes, &block)
end

#first(target = nil) ⇒ Object


30
31
32
# File 'lib/active_graph/node/query/query_proxy_methods.rb', line 30

def first(target = nil)
  first_and_last(FIRST, target)
end

#first_or_initialize(attributes = {}, &block) ⇒ Object


167
168
169
# File 'lib/active_graph/node/query/query_proxy_methods.rb', line 167

def first_or_initialize(attributes = {}, &block)
  first || initialize_by_current_chain_params(attributes, &block)
end

#first_rel_to(node) ⇒ Object

Gives you the first relationship between the last link of a QueryProxy chain and a given node Shorthand for `MATCH (start)--(other_node) WHERE ID(other_node) = #ActiveGraph::Node::Query::QueryProxyMethods.other_nodeother_node.neo_id RETURN r`

Parameters:

  • node (#neo_id, String, Enumerable)

    An object to be sent to `match_to`. See params for that method.

Returns:

  • A relationship (Relationship, CypherRelationship, EmbeddedRelationship) or nil.


138
139
140
# File 'lib/active_graph/node/query/query_proxy_methods.rb', line 138

def first_rel_to(node)
  self.match_to(node).limit(1).pluck(rel_var).first
end

#having_rel(association_name, rel_properties = {}) ⇒ QueryProxy

Matches all nodes having at least a relation

Examples:

Load all people having a friend

Person.all.having_rel(:friends).to_a # => Returns a list of `Person`

Load all people having a best friend

Person.all.having_rel(:friends, best: true).to_a # => Returns a list of `Person`

Returns:


203
204
205
206
# File 'lib/active_graph/node/query/query_proxy_methods.rb', line 203

def having_rel(association_name, rel_properties = {})
  association = association_or_fail(association_name)
  where("(#{identity})#{association.arrow_cypher(nil, rel_properties)}()")
end

#include?(other, target = nil) ⇒ Boolean

Parameters:

  • other (ActiveGraph::Node, ActiveGraph::Node, String)

    An instance of a Neo4j.rb model, a core node, or a string uuid

  • target (String, Symbol) (defaults to: nil)

    An identifier of a link in the Cypher chain

Returns:


88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/active_graph/node/query/query_proxy_methods.rb', line 88

def include?(other, target = nil)
  query_with_target(target) do |var|
    where_filter = if other.respond_to?(:neo_id) || association_id_key == :neo_id
                     "ID(#{var}) = $other_node_id"
                   else
                     "#{var}.#{association_id_key} = $other_node_id"
                   end
    node_id = other.respond_to?(:neo_id) ? other.neo_id : other
    self.where(where_filter).params(other_node_id: node_id).query.reorder.return("count(#{var}) as count")
        .first[:count].positive?
  end
end

#last(target = nil) ⇒ Object


34
35
36
# File 'lib/active_graph/node/query/query_proxy_methods.rb', line 34

def last(target = nil)
  first_and_last(LAST, target)
end

#limit_valueObject

TODO: update this with public API methods if/when they are exposed


72
73
74
75
76
# File 'lib/active_graph/node/query/query_proxy_methods.rb', line 72

def limit_value
  return unless self.query.clause?(:limit)
  limit_clause = self.query.send(:clauses).find { |clause| clause.is_a?(ActiveGraph::Core::QueryClauses::LimitClause) }
  limit_clause.instance_variable_get(:@arg)
end

#match_to(node) ⇒ ActiveGraph::Node::Query::QueryProxy

Shorthand for `MATCH (start)--(other_node) WHERE ID(other_node) = #ActiveGraph::Node::Query::QueryProxyMethods.other_nodeother_node.neo_id` The `node` param can be a persisted Node instance, any string or integer, or nil. When it's a node, it'll use the object's neo_id, which is fastest. When not nil, it'll figure out the primary key of that model. When nil, it uses `1 = 2` to prevent matching all records, which is the default behavior when nil is passed to `where` in QueryProxy.

Parameters:

  • node (#neo_id, String, Enumerable)

    A node, a string representing a node's ID, or an enumerable of nodes or IDs.

Returns:


119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/active_graph/node/query/query_proxy_methods.rb', line 119

def match_to(node)
  first_node = node.is_a?(Array) ? node.first : node
  where_arg = if first_node.respond_to?(:neo_id)
                {neo_id: node.is_a?(Array) ? node.map(&:neo_id) : node}
              elsif !node.nil?
                {association_id_key => node.is_a?(Array) ? ids_array(node) : node}
              else
                # support for null object pattern
                '1 = 2'
              end

  self.where(where_arg)
end

#not_having_rel(association_name, rel_properties = {}) ⇒ QueryProxy

Matches all nodes not having a certain relation

Examples:

Load all people not having friends

Person.all.not_having_rel(:friends).to_a # => Returns a list of `Person`

Load all people not having best friends

Person.all.not_having_rel(:friends, best: true).to_a # => Returns a list of `Person`

Returns:


217
218
219
220
# File 'lib/active_graph/node/query/query_proxy_methods.rb', line 217

def not_having_rel(association_name, rel_properties = {})
  association = association_or_fail(association_name)
  where_not("(#{identity})#{association.arrow_cypher(nil, rel_properties)}()")
end

#optional(association, node_var = nil, rel_var = nil) ⇒ Object

A shortcut for attaching a new, optional match to the end of a QueryProxy chain.


172
173
174
# File 'lib/active_graph/node/query/query_proxy_methods.rb', line 172

def optional(association, node_var = nil, rel_var = nil)
  self.send(association, node_var, rel_var, optional: true)
end

#order_propertyObject


38
39
40
41
42
# File 'lib/active_graph/node/query/query_proxy_methods.rb', line 38

def order_property
  # This should maybe be based on a setting in the association
  # rather than a hardcoded `nil`
  model ? model.id_property_name : nil
end

#propagate_context(query_proxy) ⇒ Object


50
51
52
# File 'lib/active_graph/node/query/query_proxy_methods.rb', line 50

def propagate_context(query_proxy)
  query_proxy.instance_variable_set(:@distinct, @distinct)
end

#relObject


16
17
18
# File 'lib/active_graph/node/query/query_proxy_methods.rb', line 16

def rel
  rels.first
end

#relsObject


10
11
12
13
14
# File 'lib/active_graph/node/query/query_proxy_methods.rb', line 10

def rels
  fail 'Cannot get rels without a relationship variable.' if !@rel_var

  pluck(@rel_var)
end

#rels_to(node) ⇒ Object Also known as: all_rels_to

Returns all relationships across a QueryProxy chain between a given node or array of nodes and the preceeding link.

Parameters:

  • node (#neo_id, String, Enumerable)

    An object to be sent to `match_to`. See params for that method.

Returns:

  • An enumerable of relationship objects.


145
146
147
# File 'lib/active_graph/node/query/query_proxy_methods.rb', line 145

def rels_to(node)
  self.match_to(node).pluck(rel_var)
end

#sizeObject


65
66
67
# File 'lib/active_graph/node/query/query_proxy_methods.rb', line 65

def size
  result_cache? ? result_cache_for.length : count
end