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

[View source]

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)
[View source]

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

[View source]

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

[View source]

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:

[View source]

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:

[View source]

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

[View source]

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.

[View source]

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

[View source]

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

[View source]

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

[View source]

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.

[View source]

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:

[View source]

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:

[View source]

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

[View source]

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

[View source]

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:

[View source]

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:

[View source]

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.

[View source]

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

[View source]

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

[View source]

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

def propagate_context(query_proxy)
  [:@distinct, :@rel_var].each { |var| query_proxy.instance_variable_set(var, instance_variable_get(var)) }
end

#relObject

[View source]

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

def rel
  rels.first
end

#relsObject

[View source]

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.

[View source]

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

[View source]

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