activegraph 11.3.1 → 11.5.0.alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/Gemfile +1 -1
- data/activegraph.gemspec +3 -3
- data/lib/active_graph/attribute_set.rb +0 -4
- data/lib/active_graph/base.rb +0 -3
- data/lib/active_graph/config.rb +0 -1
- data/lib/active_graph/core/instrumentable.rb +0 -5
- data/lib/active_graph/core/querable.rb +0 -5
- data/lib/active_graph/core/query.rb +6 -9
- data/lib/active_graph/core/query_clauses.rb +65 -7
- data/lib/active_graph/core/query_ext.rb +1 -1
- data/lib/active_graph/core/record.rb +0 -5
- data/lib/active_graph/core/result.rb +5 -0
- data/lib/active_graph/core/wrappable.rb +1 -1
- data/lib/active_graph/generators/active_model.rb +33 -0
- data/lib/active_graph/generators/generated_attribute.rb +17 -0
- data/lib/{rails/generators/active_graph/migration → active_graph/generators}/migration_generator.rb +0 -4
- data/lib/{rails/generators/active_graph_generator.rb → active_graph/generators/migration_helper.rb} +0 -75
- data/lib/{rails/generators/active_graph/model → active_graph/generators}/model_generator.rb +0 -4
- data/lib/active_graph/generators/source_path_helper.rb +10 -0
- data/lib/{rails/generators/active_graph/upgrade_v8 → active_graph/generators}/upgrade_v8_generator.rb +0 -4
- data/lib/active_graph/lazy_attribute_hash.rb +0 -2
- data/lib/active_graph/migration.rb +0 -3
- data/lib/active_graph/migrations/helpers.rb +0 -7
- data/lib/active_graph/migrations/runner.rb +0 -4
- data/lib/active_graph/migrations.rb +0 -8
- data/lib/active_graph/model_schema.rb +0 -1
- data/lib/active_graph/node/has_n/association.rb +0 -3
- data/lib/active_graph/node/labels.rb +1 -3
- data/lib/active_graph/node/orm_adapter.rb +0 -6
- data/lib/active_graph/node/query/{query_proxy_link.rb → query_proxy/link.rb} +92 -0
- data/lib/active_graph/node/query/query_proxy.rb +20 -3
- data/lib/active_graph/node/scope.rb +4 -43
- data/lib/active_graph/node/wrapping.rb +52 -0
- data/lib/active_graph/node.rb +1 -0
- data/lib/active_graph/railtie.rb +0 -6
- data/lib/active_graph/relationship/property.rb +0 -2
- data/lib/active_graph/relationship/wrapping.rb +26 -0
- data/lib/active_graph/shared/attributes.rb +3 -2
- data/lib/active_graph/shared/node_query_factory.rb +15 -0
- data/lib/active_graph/shared/persistence.rb +1 -1
- data/lib/active_graph/shared/query_factory.rb +0 -60
- data/lib/active_graph/shared/rel_query_factory.rb +47 -0
- data/lib/active_graph/shared/type_converters.rb +0 -6
- data/lib/active_graph/tasks/migration.rake +0 -4
- data/lib/active_graph/timestamps.rb +0 -3
- data/lib/active_graph/version.rb +1 -1
- data/lib/active_graph.rb +43 -114
- metadata +31 -22
- data/lib/active_graph/core.rb +0 -14
- data/lib/active_graph/node/node_wrapper.rb +0 -54
- data/lib/active_graph/relationship/rel_wrapper.rb +0 -31
- data/lib/active_graph/wrapper.rb +0 -4
- /data/lib/active_graph/{errors.rb → error.rb} +0 -0
- /data/lib/{rails/generators/active_graph → active_graph/generators}/migration/templates/migration.erb +0 -0
- /data/lib/{rails/generators/active_graph → active_graph/generators}/model/templates/migration.erb +0 -0
- /data/lib/{rails/generators/active_graph → active_graph/generators}/model/templates/model.erb +0 -0
- /data/lib/{rails/generators/active_graph → active_graph/generators}/upgrade_v8/templates/migration.erb +0 -0
@@ -3,6 +3,7 @@ module ActiveGraph
|
|
3
3
|
module Query
|
4
4
|
class QueryProxy
|
5
5
|
class Link
|
6
|
+
OUTER_SUBQUERY_PREFIX = 'outer_'.freeze
|
6
7
|
attr_reader :clause
|
7
8
|
|
8
9
|
def initialize(clause, arg, args = [])
|
@@ -19,6 +20,26 @@ module ActiveGraph
|
|
19
20
|
end
|
20
21
|
end
|
21
22
|
|
23
|
+
def start_of_subquery?
|
24
|
+
clause == :call_subquery_start
|
25
|
+
end
|
26
|
+
|
27
|
+
def end_of_subquery?
|
28
|
+
clause == :call_subquery_end
|
29
|
+
end
|
30
|
+
|
31
|
+
def subquery_var(original_var)
|
32
|
+
return unless start_of_subquery?
|
33
|
+
|
34
|
+
"#{OUTER_SUBQUERY_PREFIX}#{original_var}"
|
35
|
+
end
|
36
|
+
|
37
|
+
def update_outer_query_var(original_var)
|
38
|
+
return original_var unless end_of_subquery?
|
39
|
+
|
40
|
+
original_var.delete_prefix(OUTER_SUBQUERY_PREFIX)
|
41
|
+
end
|
42
|
+
|
22
43
|
class << self
|
23
44
|
def for_clause(clause, arg, model, *args)
|
24
45
|
method_to_call = "for_#{clause}_clause"
|
@@ -27,6 +48,75 @@ module ActiveGraph
|
|
27
48
|
send(method_to_call, arg, model, *args)
|
28
49
|
end
|
29
50
|
|
51
|
+
def for_union_clause(arg, model, *args)
|
52
|
+
links = []
|
53
|
+
links << new(:call_subquery_start, nil, *args)
|
54
|
+
arg[:subquery_parts].each_with_index do |subquery_part, loop_index|
|
55
|
+
links << init_union_link(arg[:proxy], model, subquery_part, loop_index, args)
|
56
|
+
end
|
57
|
+
links << new(:call_subquery_end, nil, *args)
|
58
|
+
links << post_subquery_with_clause(arg[:first_clause], args)
|
59
|
+
end
|
60
|
+
|
61
|
+
def post_subquery_with_clause(first_clause, args)
|
62
|
+
clause_arg_lambda = lambda do |v, _|
|
63
|
+
if first_clause
|
64
|
+
[v]
|
65
|
+
else
|
66
|
+
[v, "#{OUTER_SUBQUERY_PREFIX}#{v}"]
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
new(:with, clause_arg_lambda, *args)
|
71
|
+
end
|
72
|
+
|
73
|
+
def init_union_link(proxy, model, subquery_part, loop_index, args)
|
74
|
+
union_proc = if subquery_proxy_part = subquery_part.call rescue nil # rubocop:disable Style/RescueModifier
|
75
|
+
independent_union_subquery_proc(subquery_proxy_part, loop_index)
|
76
|
+
else
|
77
|
+
continuation_union_subquery_proc(proxy, model, subquery_part, loop_index)
|
78
|
+
end
|
79
|
+
new(:union, union_proc, *args)
|
80
|
+
end
|
81
|
+
|
82
|
+
def independent_union_subquery_proc(proxy, loop_index)
|
83
|
+
proxy_params = proxy.query.parameters
|
84
|
+
proxy_cypher = proxy.to_cypher
|
85
|
+
subquery_identity = proxy.identity
|
86
|
+
uniq_param_generator = uniq_param_generator_lambda
|
87
|
+
|
88
|
+
lambda do |identity, _|
|
89
|
+
proxy_params = uniq_param_generator.call(proxy_params, proxy_cypher, identity, loop_index) if proxy_params.present?
|
90
|
+
[subquery_identity, proxy_cypher, proxy_params, identity.delete_prefix(OUTER_SUBQUERY_PREFIX)]
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def continuation_union_subquery_proc(outer_proxy, model, subquery_part, loop_index) # rubocop:disable Metrics/AbcSize
|
95
|
+
lambda do |identity, _|
|
96
|
+
proxy = outer_proxy.as(identity)
|
97
|
+
proxy_with_clause = proxy.query.with(proxy.identity).with(proxy.identity).proxy_as(model, proxy.identity)
|
98
|
+
complete_query = proxy_with_clause.instance_exec(&subquery_part) || proxy_with_clause
|
99
|
+
subquery_cypher = complete_query.to_cypher
|
100
|
+
subquery_cypher = subquery_cypher.delete_prefix(proxy.to_cypher) if proxy.send(:chain).present? || proxy.starting_query
|
101
|
+
subquery_parameters = (complete_query.query.parameters.to_a - proxy.query.parameters.to_a).to_h
|
102
|
+
|
103
|
+
subquery_parameters = uniq_param_generator_lambda.call(subquery_parameters, subquery_cypher, identity, loop_index) if subquery_parameters.present?
|
104
|
+
[complete_query.identity, subquery_cypher, subquery_parameters] + [identity.delete_prefix(OUTER_SUBQUERY_PREFIX)]
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def uniq_param_generator_lambda
|
109
|
+
lambda do |proxy_params, proxy_cypher, identity, counter|
|
110
|
+
prefix = "#{identity}_UNION#{counter}_"
|
111
|
+
proxy_params.each_with_object({}) do |(param_name, param_val), new_params|
|
112
|
+
new_params_key = "#{prefix}#{param_name}".to_sym
|
113
|
+
new_params[new_params_key] = param_val
|
114
|
+
proxy_cypher.gsub!(/\$#{param_name}(?=([^`'"]|'(\\.|[^'])*'|"(\\.|[^"])*"|`(\\.|[^`])*`)*\z)/, "$#{new_params_key}")
|
115
|
+
new_params
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
30
120
|
def for_where_clause(arg, model, *args)
|
31
121
|
node_num = 1
|
32
122
|
result = []
|
@@ -104,6 +194,8 @@ module ActiveGraph
|
|
104
194
|
[for_arg(model, clause, args[0], *args[1..-1])]
|
105
195
|
elsif [:rel_where, :rel_where_not].include?(clause)
|
106
196
|
args.map { |arg| for_arg(model, clause, arg, association) }
|
197
|
+
elsif clause == :union
|
198
|
+
[for_arg(model, clause, args)]
|
107
199
|
else
|
108
200
|
args.map { |arg| for_arg(model, clause, arg) }
|
109
201
|
end
|
@@ -94,13 +94,25 @@ module ActiveGraph
|
|
94
94
|
#
|
95
95
|
# student.lessons.query_as(:l).with('your cypher here...')
|
96
96
|
def query_as(var, with_labels = true)
|
97
|
-
|
98
|
-
|
97
|
+
init_outer_query_var(var)
|
98
|
+
var_name = @outer_query_var || var
|
99
|
+
query_obj = if chain.first&.start_of_subquery? && !@association && !starting_query
|
100
|
+
_query
|
101
|
+
else
|
102
|
+
base_query(var_name, with_labels).params(@params)
|
103
|
+
end
|
104
|
+
|
105
|
+
query_from_chain(chain, query_obj, var_name).tap { |query| query.proxy_chain_level = _chain_level }
|
106
|
+
end
|
107
|
+
|
108
|
+
def init_outer_query_var(var)
|
109
|
+
chain.find(&:start_of_subquery?)&.tap { |link| @outer_query_var = link.subquery_var(var) }
|
99
110
|
end
|
100
111
|
|
101
112
|
def query_from_chain(chain, base_query, var)
|
102
113
|
chain.inject(base_query) do |query, link|
|
103
114
|
args = link.args(var, rel_var)
|
115
|
+
var = link.update_outer_query_var(var)
|
104
116
|
|
105
117
|
args.is_a?(Array) ? query.send(link.clause, *args) : query.send(link.clause, args)
|
106
118
|
end
|
@@ -143,11 +155,16 @@ module ActiveGraph
|
|
143
155
|
@model.current_scope = previous
|
144
156
|
end
|
145
157
|
|
146
|
-
METHODS = %w(where where_not rel_where rel_where_not rel_order order skip limit)
|
158
|
+
METHODS = %w(where where_not rel_where rel_where_not rel_order order skip limit union)
|
147
159
|
|
148
160
|
METHODS.each do |method|
|
149
161
|
define_method(method) { |*args| build_deeper_query_proxy(method.to_sym, args) }
|
150
162
|
end
|
163
|
+
|
164
|
+
def union(*args)
|
165
|
+
hash_args = {proxy: self, subquery_parts: args, first_clause: @chain.blank?}
|
166
|
+
build_deeper_query_proxy(:union, hash_args)
|
167
|
+
end
|
151
168
|
# Since there are rel_where and rel_order methods, it seems only natural for there to be node_where and node_order
|
152
169
|
alias node_where where
|
153
170
|
alias node_order order
|
@@ -1,9 +1,11 @@
|
|
1
|
-
require 'active_support/per_thread_registry'
|
2
|
-
|
3
1
|
module ActiveGraph::Node
|
4
2
|
module Scope
|
5
3
|
extend ActiveSupport::Concern
|
6
4
|
|
5
|
+
included do
|
6
|
+
thread_mattr_accessor :current_scope
|
7
|
+
end
|
8
|
+
|
7
9
|
module ClassMethods
|
8
10
|
# Similar to ActiveRecord scope
|
9
11
|
#
|
@@ -86,14 +88,6 @@ module ActiveGraph::Node
|
|
86
88
|
end
|
87
89
|
end
|
88
90
|
|
89
|
-
def current_scope #:nodoc:
|
90
|
-
ScopeRegistry.value_for(:current_scope, base_class.to_s)
|
91
|
-
end
|
92
|
-
|
93
|
-
def current_scope=(scope) #:nodoc:
|
94
|
-
ScopeRegistry.set_value_for(:current_scope, base_class.to_s, scope)
|
95
|
-
end
|
96
|
-
|
97
91
|
def all(new_var = nil)
|
98
92
|
var = new_var || (current_scope ? current_scope.node_identity : :n)
|
99
93
|
if current_scope
|
@@ -139,38 +133,5 @@ module ActiveGraph::Node
|
|
139
133
|
@query_proxy_or_target ||= @query_proxy || @target
|
140
134
|
end
|
141
135
|
end
|
142
|
-
|
143
|
-
|
144
|
-
# Stolen from ActiveRecord
|
145
|
-
# https://github.com/rails/rails/blob/08754f12e65a9ec79633a605e986d0f1ffa4b251/activerecord/lib/active_record/scoping.rb#L57
|
146
|
-
class ScopeRegistry # :nodoc:
|
147
|
-
extend ActiveSupport::PerThreadRegistry
|
148
|
-
|
149
|
-
VALID_SCOPE_TYPES = [:current_scope, :ignore_default_scope]
|
150
|
-
|
151
|
-
def initialize
|
152
|
-
@registry = Hash.new { |hash, key| hash[key] = {} }
|
153
|
-
end
|
154
|
-
|
155
|
-
# Obtains the value for a given +scope_name+ and +variable_name+.
|
156
|
-
def value_for(scope_type, variable_name)
|
157
|
-
raise_invalid_scope_type!(scope_type)
|
158
|
-
@registry[scope_type][variable_name]
|
159
|
-
end
|
160
|
-
|
161
|
-
# Sets the +value+ for a given +scope_type+ and +variable_name+.
|
162
|
-
def set_value_for(scope_type, variable_name, value)
|
163
|
-
raise_invalid_scope_type!(scope_type)
|
164
|
-
@registry[scope_type][variable_name] = value
|
165
|
-
end
|
166
|
-
|
167
|
-
private
|
168
|
-
|
169
|
-
def raise_invalid_scope_type!(scope_type)
|
170
|
-
return if VALID_SCOPE_TYPES.include?(scope_type)
|
171
|
-
|
172
|
-
fail ArgumentError, "Invalid scope type '#{scope_type}' sent to the registry. Scope types must be included in VALID_SCOPE_TYPES"
|
173
|
-
end
|
174
|
-
end
|
175
136
|
end
|
176
137
|
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module ActiveGraph
|
2
|
+
module Node
|
3
|
+
module Wrapping
|
4
|
+
# Only load classes once for performance
|
5
|
+
CONSTANTS_FOR_LABELS_CACHE = {}
|
6
|
+
|
7
|
+
class << self
|
8
|
+
def wrapper(node)
|
9
|
+
found_class = class_to_wrap(node.labels)
|
10
|
+
return node unless found_class
|
11
|
+
|
12
|
+
found_class.new.tap do |wrapped_node|
|
13
|
+
wrapped_node.init_on_load(node, node.properties)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def class_to_wrap(labels)
|
18
|
+
load_classes_from_labels(labels)
|
19
|
+
ActiveGraph::Node::Labels.model_for_labels(labels).tap do |model_class|
|
20
|
+
populate_constants_for_labels_cache(model_class, labels)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def load_classes_from_labels(labels)
|
27
|
+
labels.each { |label| constant_for_label(label) }
|
28
|
+
end
|
29
|
+
|
30
|
+
def constant_for_label(label)
|
31
|
+
CONSTANTS_FOR_LABELS_CACHE[label] ||= constantized_label(label)
|
32
|
+
end
|
33
|
+
|
34
|
+
def constantized_label(label)
|
35
|
+
"#{association_model_namespace}::#{label}".constantize
|
36
|
+
rescue NameError, LoadError
|
37
|
+
nil
|
38
|
+
end
|
39
|
+
|
40
|
+
def populate_constants_for_labels_cache(model_class, labels)
|
41
|
+
labels.each do |label|
|
42
|
+
CONSTANTS_FOR_LABELS_CACHE[label] ||= model_class
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def association_model_namespace
|
47
|
+
ActiveGraph::Config.association_model_namespace_string
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/lib/active_graph/node.rb
CHANGED
data/lib/active_graph/railtie.rb
CHANGED
@@ -1,9 +1,3 @@
|
|
1
|
-
require 'active_support/notifications'
|
2
|
-
require 'rails/railtie'
|
3
|
-
# Need the action_dispatch railtie to have action_dispatch.rescue_responses initialized correctly
|
4
|
-
require 'action_dispatch/railtie'
|
5
|
-
require 'active_graph'
|
6
|
-
|
7
1
|
module ActiveGraph
|
8
2
|
class Railtie < ::Rails::Railtie
|
9
3
|
def empty_config
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module ActiveGraph
|
2
|
+
module Relationship
|
3
|
+
module Wrapping
|
4
|
+
class << self
|
5
|
+
def wrapper(rel)
|
6
|
+
rel.properties.symbolize_keys!
|
7
|
+
begin
|
8
|
+
most_concrete_class = class_from_type(rel.type).constantize
|
9
|
+
return rel unless most_concrete_class < ActiveGraph::Relationship
|
10
|
+
most_concrete_class.new
|
11
|
+
rescue NameError => e
|
12
|
+
raise e unless e.message =~ /(uninitialized|wrong) constant/
|
13
|
+
|
14
|
+
return rel
|
15
|
+
end.tap do |wrapped_rel|
|
16
|
+
wrapped_rel.init_on_load(rel, rel.start_node_id, rel.end_node_id, rel.type)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def class_from_type(type)
|
21
|
+
ActiveGraph::Relationship::Types::WRAPPED_CLASSES[type] || ActiveGraph::Relationship::Types::WRAPPED_CLASSES[type] = type.to_s.downcase.camelize
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -18,9 +18,10 @@ module ActiveGraph::Shared
|
|
18
18
|
|
19
19
|
# Methods deprecated on the Object class which can be safely overridden
|
20
20
|
DEPRECATED_OBJECT_METHODS = %w(id type)
|
21
|
+
ATTRIBUTES_METHOD_PATTERNS = Gem::Requirement.create('>= 7.1').satisfied_by?(Gem.loaded_specs["activesupport"].version) ? :attribute_method_patterns : :attribute_method_matchers
|
21
22
|
|
22
23
|
included do
|
23
|
-
attribute_method_suffix '' if
|
24
|
+
attribute_method_suffix '' if send(ATTRIBUTES_METHOD_PATTERNS).none? { |matcher| matcher.prefix == '' && matcher.suffix == '' }
|
24
25
|
attribute_method_suffix '='
|
25
26
|
attribute_method_suffix '?'
|
26
27
|
end
|
@@ -204,7 +205,7 @@ module ActiveGraph::Shared
|
|
204
205
|
|
205
206
|
# Expand an attribute name into its generated methods names
|
206
207
|
def attribute_methods(name)
|
207
|
-
|
208
|
+
send(ATTRIBUTES_METHOD_PATTERNS).map { |matcher| matcher.method_name name }
|
208
209
|
end
|
209
210
|
|
210
211
|
# Ruby inherited hook to assign superclass attributes to subclasses
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module ActiveGraph::Shared
|
2
|
+
class NodeQueryFactory < QueryFactory
|
3
|
+
protected
|
4
|
+
|
5
|
+
def match_string
|
6
|
+
"(#{identifier})"
|
7
|
+
end
|
8
|
+
|
9
|
+
def create_query
|
10
|
+
return match_query if graph_object.persisted?
|
11
|
+
labels = graph_object.labels_for_create.map { |l| ":`#{l}`" }.join
|
12
|
+
base_query.create("(#{identifier}#{labels} $#{identifier}_params)").params(identifier_params => graph_object.props_for_create)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -217,7 +217,7 @@ module ActiveGraph::Shared
|
|
217
217
|
if self.new_record?
|
218
218
|
"#{model_cache_key}/new"
|
219
219
|
elsif self.respond_to?(:updated_at) && !self.updated_at.blank?
|
220
|
-
"#{model_cache_key}/#{neo_id}-#{self.updated_at.utc.
|
220
|
+
"#{model_cache_key}/#{neo_id}-#{self.updated_at.utc.to_fs(:number)}"
|
221
221
|
else
|
222
222
|
"#{model_cache_key}/#{neo_id}"
|
223
223
|
end
|
@@ -59,64 +59,4 @@ module ActiveGraph::Shared
|
|
59
59
|
@identifier_params ||= "#{identifier}_params"
|
60
60
|
end
|
61
61
|
end
|
62
|
-
|
63
|
-
class NodeQueryFactory < QueryFactory
|
64
|
-
protected
|
65
|
-
|
66
|
-
def match_string
|
67
|
-
"(#{identifier})"
|
68
|
-
end
|
69
|
-
|
70
|
-
def create_query
|
71
|
-
return match_query if graph_object.persisted?
|
72
|
-
labels = graph_object.labels_for_create.map { |l| ":`#{l}`" }.join
|
73
|
-
base_query.create("(#{identifier}#{labels} $#{identifier}_params)").params(identifier_params => graph_object.props_for_create)
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
class RelQueryFactory < QueryFactory
|
78
|
-
protected
|
79
|
-
|
80
|
-
def match_string
|
81
|
-
"(#{graph_object.from_node_identifier})-[#{identifier}]->()"
|
82
|
-
end
|
83
|
-
|
84
|
-
def create_query
|
85
|
-
return match_query if graph_object.persisted?
|
86
|
-
create_props, set_props = filtered_props
|
87
|
-
base_query.send(graph_object.create_method, query_string(create_props)).break
|
88
|
-
.set(identifier => set_props)
|
89
|
-
.params(params(create_props))
|
90
|
-
end
|
91
|
-
|
92
|
-
private
|
93
|
-
|
94
|
-
def filtered_props
|
95
|
-
ActiveGraph::Shared::FilteredHash.new(graph_object.props_for_create, graph_object.creates_unique_option).filtered_base
|
96
|
-
end
|
97
|
-
|
98
|
-
def query_string(create_props)
|
99
|
-
"(#{graph_object.from_node_identifier})-[#{identifier}:`#{graph_object.type}` #{pattern(create_props)}]->(#{graph_object.to_node_identifier})"
|
100
|
-
end
|
101
|
-
|
102
|
-
def params(create_props)
|
103
|
-
unique? ? create_props.transform_keys { |key| scoped(key).to_sym } : { namespace.to_sym => create_props }
|
104
|
-
end
|
105
|
-
|
106
|
-
def unique?
|
107
|
-
graph_object.create_method == :create_unique
|
108
|
-
end
|
109
|
-
|
110
|
-
def pattern(create_props)
|
111
|
-
unique? ? "{#{create_props.keys.map { |key| "#{key}: $#{scoped(key)}" }.join(', ')}}" : "$#{namespace}"
|
112
|
-
end
|
113
|
-
|
114
|
-
def scoped(key)
|
115
|
-
"#{namespace}_#{key}"
|
116
|
-
end
|
117
|
-
|
118
|
-
def namespace
|
119
|
-
"#{identifier}_create_props"
|
120
|
-
end
|
121
|
-
end
|
122
62
|
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module ActiveGraph::Shared
|
2
|
+
class RelQueryFactory < QueryFactory
|
3
|
+
protected
|
4
|
+
|
5
|
+
def match_string
|
6
|
+
"(#{graph_object.from_node_identifier})-[#{identifier}]->()"
|
7
|
+
end
|
8
|
+
|
9
|
+
def create_query
|
10
|
+
return match_query if graph_object.persisted?
|
11
|
+
create_props, set_props = filtered_props
|
12
|
+
base_query.send(graph_object.create_method, query_string(create_props)).break
|
13
|
+
.set(identifier => set_props)
|
14
|
+
.params(params(create_props))
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def filtered_props
|
20
|
+
ActiveGraph::Shared::FilteredHash.new(graph_object.props_for_create, graph_object.creates_unique_option).filtered_base
|
21
|
+
end
|
22
|
+
|
23
|
+
def query_string(create_props)
|
24
|
+
"(#{graph_object.from_node_identifier})-[#{identifier}:`#{graph_object.type}` #{pattern(create_props)}]->(#{graph_object.to_node_identifier})"
|
25
|
+
end
|
26
|
+
|
27
|
+
def params(create_props)
|
28
|
+
unique? ? create_props.transform_keys { |key| scoped(key).to_sym } : { namespace.to_sym => create_props }
|
29
|
+
end
|
30
|
+
|
31
|
+
def unique?
|
32
|
+
graph_object.create_method == :create_unique
|
33
|
+
end
|
34
|
+
|
35
|
+
def pattern(create_props)
|
36
|
+
unique? ? "{#{create_props.keys.map { |key| "#{key}: $#{scoped(key)}" }.join(', ')}}" : "$#{namespace}"
|
37
|
+
end
|
38
|
+
|
39
|
+
def scoped(key)
|
40
|
+
"#{namespace}_#{key}"
|
41
|
+
end
|
42
|
+
|
43
|
+
def namespace
|
44
|
+
"#{identifier}_create_props"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/lib/active_graph/version.rb
CHANGED