Class: ActiveGraph::Node::Query::QueryProxy::Link

Inherits:
Object
  • Object
show all
Defined in:
lib/active_graph/node/query/query_proxy/link.rb

Constant Summary collapse

OUTER_SUBQUERY_PREFIX =
'outer_'.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(clause, arg, args = []) ⇒ Link

Returns a new instance of Link.



9
10
11
12
13
# File 'lib/active_graph/node/query/query_proxy/link.rb', line 9

def initialize(clause, arg, args = [])
  @clause = clause
  @arg = arg
  @args = args
end

Instance Attribute Details

#clauseObject (readonly)

Returns the value of attribute clause.



7
8
9
# File 'lib/active_graph/node/query/query_proxy/link.rb', line 7

def clause
  @clause
end

Class Method Details

.continuation_union_subquery_proc(outer_proxy, model, subquery_part, loop_index) ⇒ Object

rubocop:disable Metrics/AbcSize



94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/active_graph/node/query/query_proxy/link.rb', line 94

def continuation_union_subquery_proc(outer_proxy, model, subquery_part, loop_index) # rubocop:disable Metrics/AbcSize
  lambda do |identity, _|
    proxy = outer_proxy.as(identity)
    proxy_with_clause = proxy.query.with(proxy.identity).with(proxy.identity).proxy_as(model, proxy.identity)
    complete_query = proxy_with_clause.instance_exec(&subquery_part) || proxy_with_clause
    subquery_cypher = complete_query.to_cypher
    subquery_cypher = subquery_cypher.delete_prefix(proxy.to_cypher) if proxy.send(:chain).present? || proxy.starting_query
    subquery_parameters = (complete_query.query.parameters.to_a - proxy.query.parameters.to_a).to_h

    subquery_parameters = uniq_param_generator_lambda.call(subquery_parameters, subquery_cypher, identity, loop_index) if subquery_parameters.present?
    [complete_query.identity, subquery_cypher, subquery_parameters] + [identity.delete_prefix(OUTER_SUBQUERY_PREFIX)]
  end
end

.converted_key(model, key) ⇒ Object



225
226
227
228
229
230
231
# File 'lib/active_graph/node/query/query_proxy/link.rb', line 225

def converted_key(model, key)
  if key.to_sym == :id
    model ? model.id_property_name : :uuid
  else
    key
  end
end

.converted_keys(model, arg) ⇒ Object



221
222
223
# File 'lib/active_graph/node/query/query_proxy/link.rb', line 221

def converted_keys(model, arg)
  arg.is_a?(Hash) ? Hash[arg.map { |key, value| [converted_key(model, key), value] }] : arg
end

.converted_value(model, key, value) ⇒ Object



233
234
235
# File 'lib/active_graph/node/query/query_proxy/link.rb', line 233

def converted_value(model, key, value)
  model.declared_properties.value_for_where(key, value)
end

.for_arg(model, clause, arg, *args) ⇒ Object



215
216
217
218
219
# File 'lib/active_graph/node/query/query_proxy/link.rb', line 215

def for_arg(model, clause, arg, *args)
  default = [Link.new(clause, arg, *args)]

  Link.for_clause(clause, arg, model, *args) || default
end

.for_args(model, clause, args, association = nil) ⇒ Object



203
204
205
206
207
208
209
210
211
212
213
# File 'lib/active_graph/node/query/query_proxy/link.rb', line 203

def for_args(model, clause, args, association = nil)
  if [:where, :where_not].include?(clause) && args[0].is_a?(String) # Better way?
    [for_arg(model, clause, args[0], *args[1..-1])]
  elsif [:rel_where, :rel_where_not].include?(clause)
    args.map { |arg| for_arg(model, clause, arg, association) }
  elsif clause == :union
    [for_arg(model, clause, args)]
  else
    args.map { |arg| for_arg(model, clause, arg) }
  end
end

.for_association(name, value, n_string, model) ⇒ Object



170
171
172
173
174
175
176
177
178
# File 'lib/active_graph/node/query/query_proxy/link.rb', line 170

def for_association(name, value, n_string, model)
  neo_id = value.try(:neo_id) || value
  fail ArgumentError, "Invalid value for '#{name}' condition" unless neo_id.is_a?(String)

  [
    new(:match, ->(v, _) { "(#{v})#{model.associations[name].arrow_cypher}(#{n_string})" }),
    new(:where, ->(_, _) { {"elementId(#{n_string})" => neo_id} })
  ]
end

.for_clause(clause, arg, model, *args) ⇒ Object



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

def for_clause(clause, arg, model, *args)
  method_to_call = "for_#{clause}_clause"
  return unless respond_to?(method_to_call)

  send(method_to_call, arg, model, *args)
end

.for_order_clause(arg, model) ⇒ Object



199
200
201
# File 'lib/active_graph/node/query/query_proxy/link.rb', line 199

def for_order_clause(arg, model)
  [new(:order, ->(v, _) { arg.is_a?(String) ? arg : {v => converted_keys(model, arg)} })]
end

.for_rel_order_clause(arg, _) ⇒ Object



195
196
197
# File 'lib/active_graph/node/query/query_proxy/link.rb', line 195

def for_rel_order_clause(arg, _)
  [new(:order, ->(_, v) { arg.is_a?(String) ? arg : {v => arg} })]
end

.for_rel_where_clause(arg, _, association) ⇒ Object

We don’t accept strings here. If you want to use a string, just use where.



181
182
183
184
185
186
187
# File 'lib/active_graph/node/query/query_proxy/link.rb', line 181

def for_rel_where_clause(arg, _, association)
  arg.each_with_object([]) do |(key, value), result|
    rel_class = association.relationship_class if association.relationship_class
    val =  rel_class ? converted_value(rel_class, key, value) : value
    result << new(:where, ->(_, rel_var) { {rel_var => {key => val}} })
  end
end

.for_rel_where_not_clause(*args) ⇒ Object



189
190
191
192
193
# File 'lib/active_graph/node/query/query_proxy/link.rb', line 189

def for_rel_where_not_clause(*args)
  for_rel_where_clause(*args).each do |link|
    link.instance_variable_set('@clause', :where_not)
  end
end

.for_union_clause(arg, model, *args) ⇒ Object



51
52
53
54
55
56
57
58
59
# File 'lib/active_graph/node/query/query_proxy/link.rb', line 51

def for_union_clause(arg, model, *args)
  links = []
  links << new(:call_subquery_start, nil, *args)
  arg[:subquery_parts].each_with_index do |subquery_part, loop_index|
    links << init_union_link(arg[:proxy], model, subquery_part, loop_index, args)
  end
  links << new(:call_subquery_end, nil, *args)
  links << post_subquery_with_clause(arg[:first_clause], args)
end

.for_where_clause(arg, model, *args) ⇒ Object Also known as: for_node_where_clause



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/active_graph/node/query/query_proxy/link.rb', line 120

def for_where_clause(arg, model, *args)
  node_num = 1
  result = []
  if arg.is_a?(Hash)
    arg.each do |key, value|
      if model && model.association?(key)
        result += for_association(key, value, "n#{node_num}", model)
        node_num += 1
      else
        result << new_for_key_and_value(model, key, value)
      end
    end
  elsif arg.is_a?(String)
    result << new(:where, arg, args)
  end
  result
end

.for_where_not_clause(*args) ⇒ Object



139
140
141
142
143
# File 'lib/active_graph/node/query/query_proxy/link.rb', line 139

def for_where_not_clause(*args)
  for_where_clause(*args).each do |link|
    link.instance_variable_set('@clause', :where_not)
  end
end

.independent_union_subquery_proc(proxy, loop_index) ⇒ Object



82
83
84
85
86
87
88
89
90
91
92
# File 'lib/active_graph/node/query/query_proxy/link.rb', line 82

def independent_union_subquery_proc(proxy, loop_index)
  proxy_params = proxy.query.parameters
  proxy_cypher = proxy.to_cypher
  subquery_identity = proxy.identity
  uniq_param_generator = uniq_param_generator_lambda

  lambda do |identity, _|
    proxy_params = uniq_param_generator.call(proxy_params, proxy_cypher, identity, loop_index) if proxy_params.present?
    [subquery_identity, proxy_cypher, proxy_params, identity.delete_prefix(OUTER_SUBQUERY_PREFIX)]
  end
end


73
74
75
76
77
78
79
80
# File 'lib/active_graph/node/query/query_proxy/link.rb', line 73

def init_union_link(proxy, model, subquery_part, loop_index, args)
  union_proc = if subquery_proxy_part = subquery_part.call rescue nil # rubocop:disable Style/RescueModifier
                 independent_union_subquery_proc(subquery_proxy_part, loop_index)
               else
                 continuation_union_subquery_proc(proxy, model, subquery_part, loop_index)
               end
  new(:union, union_proc, *args)
end

.new_for_key_and_value(model, key, value) ⇒ Object



145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/active_graph/node/query/query_proxy/link.rb', line 145

def new_for_key_and_value(model, key, value)
  key = converted_key(model, key)

  val = if !model
          value
        elsif key == model.id_property_name
          try_id(value)
        else
          converted_value(model, key, value)
        end

  new(:where, ->(v, _) { {v => {key => val}} })
end

.post_subquery_with_clause(first_clause, args) ⇒ Object



61
62
63
64
65
66
67
68
69
70
71
# File 'lib/active_graph/node/query/query_proxy/link.rb', line 61

def post_subquery_with_clause(first_clause, args)
  clause_arg_lambda = lambda do |v, _|
    if first_clause
      [v]
    else
      [v, "#{OUTER_SUBQUERY_PREFIX}#{v}"]
    end
  end

  new(:with, clause_arg_lambda, *args)
end

.uniq_param_generator_lambdaObject



108
109
110
111
112
113
114
115
116
117
118
# File 'lib/active_graph/node/query/query_proxy/link.rb', line 108

def uniq_param_generator_lambda
  lambda do |proxy_params, proxy_cypher, identity, counter|
    prefix = "#{identity}_UNION#{counter}_"
    proxy_params.each_with_object({}) do |(param_name, param_val), new_params|
      new_params_key = "#{prefix}#{param_name}".to_sym
      new_params[new_params_key] = param_val
      proxy_cypher.gsub!(/\$#{param_name}(?=([^`'"]|'(\\.|[^'])*'|"(\\.|[^"])*"|`(\\.|[^`])*`)*\z)/, "$#{new_params_key}")
      new_params
    end
  end
end

Instance Method Details

#args(var, rel_var) ⇒ Object



15
16
17
18
19
20
21
# File 'lib/active_graph/node/query/query_proxy/link.rb', line 15

def args(var, rel_var)
  if @arg.respond_to?(:call)
    @arg.call(var, rel_var)
  else
    [@arg] + @args
  end
end

#end_of_subquery?Boolean

Returns:



27
28
29
# File 'lib/active_graph/node/query/query_proxy/link.rb', line 27

def end_of_subquery?
  clause == :call_subquery_end
end

#start_of_subquery?Boolean

Returns:



23
24
25
# File 'lib/active_graph/node/query/query_proxy/link.rb', line 23

def start_of_subquery?
  clause == :call_subquery_start
end

#subquery_var(original_var) ⇒ Object



31
32
33
34
35
# File 'lib/active_graph/node/query/query_proxy/link.rb', line 31

def subquery_var(original_var)
  return unless start_of_subquery?

  "#{OUTER_SUBQUERY_PREFIX}#{original_var}"
end

#update_outer_query_var(original_var) ⇒ Object



37
38
39
40
41
# File 'lib/active_graph/node/query/query_proxy/link.rb', line 37

def update_outer_query_var(original_var)
  return original_var unless end_of_subquery?

  original_var.delete_prefix(OUTER_SUBQUERY_PREFIX)
end