neo4j_legacy 7.2.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +1357 -0
- data/CONTRIBUTORS +8 -0
- data/Gemfile +38 -0
- data/README.md +103 -0
- data/bin/neo4j-jars +33 -0
- data/bin/rake +17 -0
- data/config/locales/en.yml +5 -0
- data/config/neo4j/add_classnames.yml +1 -0
- data/config/neo4j/config.yml +35 -0
- data/lib/active_support/per_thread_registry.rb +1 -0
- data/lib/backports/action_controller/metal/strong_parameters.rb +672 -0
- data/lib/backports/active_model/forbidden_attributes_protection.rb +30 -0
- data/lib/backports/active_support/concern.rb +13 -0
- data/lib/backports/active_support/core_ext/module/attribute_accessors.rb +10 -0
- data/lib/backports/active_support/logger.rb +99 -0
- data/lib/backports/active_support/logger_silence.rb +27 -0
- data/lib/backports/active_support/logger_thread_safe_level.rb +32 -0
- data/lib/backports/active_support/per_thread_registry.rb +60 -0
- data/lib/backports.rb +4 -0
- data/lib/neo4j/active_node/callbacks.rb +8 -0
- data/lib/neo4j/active_node/dependent/association_methods.rb +48 -0
- data/lib/neo4j/active_node/dependent/query_proxy_methods.rb +50 -0
- data/lib/neo4j/active_node/dependent.rb +11 -0
- data/lib/neo4j/active_node/enum.rb +29 -0
- data/lib/neo4j/active_node/has_n/association/rel_factory.rb +61 -0
- data/lib/neo4j/active_node/has_n/association/rel_wrapper.rb +23 -0
- data/lib/neo4j/active_node/has_n/association.rb +280 -0
- data/lib/neo4j/active_node/has_n/association_cypher_methods.rb +108 -0
- data/lib/neo4j/active_node/has_n.rb +532 -0
- data/lib/neo4j/active_node/id_property/accessor.rb +62 -0
- data/lib/neo4j/active_node/id_property.rb +187 -0
- data/lib/neo4j/active_node/initialize.rb +21 -0
- data/lib/neo4j/active_node/labels/index.rb +87 -0
- data/lib/neo4j/active_node/labels/reloading.rb +21 -0
- data/lib/neo4j/active_node/labels.rb +198 -0
- data/lib/neo4j/active_node/node_wrapper.rb +52 -0
- data/lib/neo4j/active_node/orm_adapter.rb +82 -0
- data/lib/neo4j/active_node/persistence.rb +175 -0
- data/lib/neo4j/active_node/property.rb +60 -0
- data/lib/neo4j/active_node/query/query_proxy.rb +361 -0
- data/lib/neo4j/active_node/query/query_proxy_eager_loading.rb +61 -0
- data/lib/neo4j/active_node/query/query_proxy_enumerable.rb +90 -0
- data/lib/neo4j/active_node/query/query_proxy_find_in_batches.rb +19 -0
- data/lib/neo4j/active_node/query/query_proxy_link.rb +117 -0
- data/lib/neo4j/active_node/query/query_proxy_methods.rb +210 -0
- data/lib/neo4j/active_node/query/query_proxy_methods_of_mass_updating.rb +83 -0
- data/lib/neo4j/active_node/query.rb +76 -0
- data/lib/neo4j/active_node/query_methods.rb +65 -0
- data/lib/neo4j/active_node/reflection.rb +86 -0
- data/lib/neo4j/active_node/rels.rb +11 -0
- data/lib/neo4j/active_node/scope.rb +146 -0
- data/lib/neo4j/active_node/unpersisted.rb +48 -0
- data/lib/neo4j/active_node/validations.rb +59 -0
- data/lib/neo4j/active_node.rb +105 -0
- data/lib/neo4j/active_rel/callbacks.rb +15 -0
- data/lib/neo4j/active_rel/initialize.rb +28 -0
- data/lib/neo4j/active_rel/persistence/query_factory.rb +95 -0
- data/lib/neo4j/active_rel/persistence.rb +114 -0
- data/lib/neo4j/active_rel/property.rb +95 -0
- data/lib/neo4j/active_rel/query.rb +95 -0
- data/lib/neo4j/active_rel/rel_wrapper.rb +22 -0
- data/lib/neo4j/active_rel/related_node.rb +83 -0
- data/lib/neo4j/active_rel/types.rb +82 -0
- data/lib/neo4j/active_rel/validations.rb +8 -0
- data/lib/neo4j/active_rel.rb +67 -0
- data/lib/neo4j/class_arguments.rb +39 -0
- data/lib/neo4j/config.rb +124 -0
- data/lib/neo4j/core/query.rb +22 -0
- data/lib/neo4j/errors.rb +28 -0
- data/lib/neo4j/migration.rb +127 -0
- data/lib/neo4j/paginated.rb +27 -0
- data/lib/neo4j/railtie.rb +169 -0
- data/lib/neo4j/schema/operation.rb +91 -0
- data/lib/neo4j/shared/attributes.rb +220 -0
- data/lib/neo4j/shared/callbacks.rb +64 -0
- data/lib/neo4j/shared/cypher.rb +37 -0
- data/lib/neo4j/shared/declared_properties.rb +204 -0
- data/lib/neo4j/shared/declared_property/index.rb +37 -0
- data/lib/neo4j/shared/declared_property.rb +118 -0
- data/lib/neo4j/shared/enum.rb +148 -0
- data/lib/neo4j/shared/filtered_hash.rb +79 -0
- data/lib/neo4j/shared/identity.rb +28 -0
- data/lib/neo4j/shared/initialize.rb +28 -0
- data/lib/neo4j/shared/marshal.rb +23 -0
- data/lib/neo4j/shared/mass_assignment.rb +58 -0
- data/lib/neo4j/shared/permitted_attributes.rb +28 -0
- data/lib/neo4j/shared/persistence.rb +231 -0
- data/lib/neo4j/shared/property.rb +220 -0
- data/lib/neo4j/shared/query_factory.rb +101 -0
- data/lib/neo4j/shared/rel_type_converters.rb +43 -0
- data/lib/neo4j/shared/serialized_properties.rb +30 -0
- data/lib/neo4j/shared/type_converters.rb +418 -0
- data/lib/neo4j/shared/typecasted_attributes.rb +98 -0
- data/lib/neo4j/shared/typecaster.rb +53 -0
- data/lib/neo4j/shared/validations.rb +48 -0
- data/lib/neo4j/shared.rb +51 -0
- data/lib/neo4j/tasks/migration.rake +24 -0
- data/lib/neo4j/timestamps/created.rb +9 -0
- data/lib/neo4j/timestamps/updated.rb +9 -0
- data/lib/neo4j/timestamps.rb +11 -0
- data/lib/neo4j/type_converters.rb +7 -0
- data/lib/neo4j/version.rb +3 -0
- data/lib/neo4j/wrapper.rb +4 -0
- data/lib/neo4j.rb +96 -0
- data/lib/rails/generators/neo4j/model/model_generator.rb +86 -0
- data/lib/rails/generators/neo4j/model/templates/model.erb +15 -0
- data/lib/rails/generators/neo4j_generator.rb +67 -0
- data/neo4j.gemspec +43 -0
- metadata +389 -0
@@ -0,0 +1,13 @@
|
|
1
|
+
unless ActiveSupport::Concern.method_defined? :class_methods
|
2
|
+
module ActiveSupport
|
3
|
+
module Concern
|
4
|
+
def class_methods(&class_methods_module_definition)
|
5
|
+
mod = const_defined?(:ClassMethods, false) ?
|
6
|
+
const_get(:ClassMethods) :
|
7
|
+
const_set(:ClassMethods, Module.new)
|
8
|
+
|
9
|
+
mod.module_eval(&class_methods_module_definition)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
unless defined? ActiveSupport::Logger
|
2
|
+
require 'active_support/core_ext/module/attribute_accessors'
|
3
|
+
require 'backports/active_support/core_ext/module/attribute_accessors'
|
4
|
+
require 'backports/active_support/logger_silence'
|
5
|
+
require 'backports/active_support/logger_thread_safe_level'
|
6
|
+
require 'logger'
|
7
|
+
|
8
|
+
module ActiveSupport
|
9
|
+
class Logger < ::Logger
|
10
|
+
include ActiveSupport::LoggerThreadSafeLevel
|
11
|
+
include LoggerSilence
|
12
|
+
|
13
|
+
# Broadcasts logs to multiple loggers.
|
14
|
+
def self.broadcast(logger) # :nodoc:
|
15
|
+
Module.new do
|
16
|
+
define_method(:add) do |*args, &block|
|
17
|
+
logger.add(*args, &block)
|
18
|
+
super(*args, &block)
|
19
|
+
end
|
20
|
+
|
21
|
+
define_method(:<<) do |x|
|
22
|
+
logger << x
|
23
|
+
super(x)
|
24
|
+
end
|
25
|
+
|
26
|
+
define_method(:close) do
|
27
|
+
logger.close
|
28
|
+
super()
|
29
|
+
end
|
30
|
+
|
31
|
+
define_method(:progname=) do |name|
|
32
|
+
logger.progname = name
|
33
|
+
super(name)
|
34
|
+
end
|
35
|
+
|
36
|
+
define_method(:formatter=) do |formatter|
|
37
|
+
logger.formatter = formatter
|
38
|
+
super(formatter)
|
39
|
+
end
|
40
|
+
|
41
|
+
define_method(:level=) do |level|
|
42
|
+
logger.level = level
|
43
|
+
super(level)
|
44
|
+
end
|
45
|
+
|
46
|
+
define_method(:local_level=) do |level|
|
47
|
+
logger.local_level = level if logger.respond_to?(:local_level=)
|
48
|
+
super(level) if respond_to?(:local_level=)
|
49
|
+
end
|
50
|
+
|
51
|
+
define_method(:silence) do |level = Logger::ERROR, &block|
|
52
|
+
if logger.respond_to?(:silence) && logger.method(:silence).owner != ::Kernel
|
53
|
+
logger.silence(level) do
|
54
|
+
if respond_to?(:silence) && method(:silence).owner != ::Kernel
|
55
|
+
super(level, &block)
|
56
|
+
else
|
57
|
+
block.call(self)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
else
|
61
|
+
if respond_to?(:silence) && method(:silence).owner != ::Kernel
|
62
|
+
super(level, &block)
|
63
|
+
else
|
64
|
+
block.call(self)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def initialize(*args)
|
72
|
+
super
|
73
|
+
@formatter = SimpleFormatter.new
|
74
|
+
after_initialize if respond_to? :after_initialize
|
75
|
+
end
|
76
|
+
|
77
|
+
def add(severity, message = nil, progname = nil, &block)
|
78
|
+
return true if @logdev.nil? || (severity || UNKNOWN) < level
|
79
|
+
super
|
80
|
+
end
|
81
|
+
|
82
|
+
Logger::Severity.constants.each do |severity|
|
83
|
+
class_eval(<<-EOT, __FILE__, __LINE__ + 1)
|
84
|
+
def #{severity.downcase}? # def debug?
|
85
|
+
Logger::#{severity} >= level # DEBUG >= level
|
86
|
+
end # end
|
87
|
+
EOT
|
88
|
+
end
|
89
|
+
|
90
|
+
# Simple formatter which only displays the message.
|
91
|
+
class SimpleFormatter < ::Logger::Formatter
|
92
|
+
# This method is invoked when a log event occurs
|
93
|
+
def call(severity, timestamp, progname, msg)
|
94
|
+
"#{String === msg ? msg : msg.inspect}\n"
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
require 'thread_safe'
|
3
|
+
|
4
|
+
module LoggerSilence
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
cattr_accessor :silencer
|
9
|
+
self.silencer = true
|
10
|
+
end
|
11
|
+
|
12
|
+
# Silences the logger for the duration of the block.
|
13
|
+
def silence(temporary_level = Logger::ERROR)
|
14
|
+
if silencer
|
15
|
+
begin
|
16
|
+
old_local_level = local_level
|
17
|
+
self.local_level = temporary_level
|
18
|
+
|
19
|
+
yield self
|
20
|
+
ensure
|
21
|
+
self.local_level = old_local_level
|
22
|
+
end
|
23
|
+
else
|
24
|
+
yield self
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
require 'thread_safe'
|
3
|
+
|
4
|
+
module ActiveSupport
|
5
|
+
module LoggerThreadSafeLevel
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
def after_initialize
|
9
|
+
@local_levels = ThreadSafe::Cache.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def local_log_id
|
13
|
+
Thread.current.__id__
|
14
|
+
end
|
15
|
+
|
16
|
+
def local_level
|
17
|
+
@local_levels[local_log_id]
|
18
|
+
end
|
19
|
+
|
20
|
+
def local_level=(level)
|
21
|
+
if level
|
22
|
+
@local_levels[local_log_id] = level
|
23
|
+
else
|
24
|
+
@local_levels.delete(local_log_id)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def level
|
29
|
+
local_level || super
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
unless defined? ActiveSupport::PerThreadRegistry
|
2
|
+
require "active_support/core_ext/module/delegation"
|
3
|
+
|
4
|
+
module ActiveSupport
|
5
|
+
# NOTE: This approach has been deprecated for end-user code in favor of {thread_mattr_accessor}[rdoc-ref:Module#thread_mattr_accessor] and friends.
|
6
|
+
# Please use that approach instead.
|
7
|
+
#
|
8
|
+
# This module is used to encapsulate access to thread local variables.
|
9
|
+
#
|
10
|
+
# Instead of polluting the thread locals namespace:
|
11
|
+
#
|
12
|
+
# Thread.current[:connection_handler]
|
13
|
+
#
|
14
|
+
# you define a class that extends this module:
|
15
|
+
#
|
16
|
+
# module ActiveRecord
|
17
|
+
# class RuntimeRegistry
|
18
|
+
# extend ActiveSupport::PerThreadRegistry
|
19
|
+
#
|
20
|
+
# attr_accessor :connection_handler
|
21
|
+
# end
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# and invoke the declared instance accessors as class methods. So
|
25
|
+
#
|
26
|
+
# ActiveRecord::RuntimeRegistry.connection_handler = connection_handler
|
27
|
+
#
|
28
|
+
# sets a connection handler local to the current thread, and
|
29
|
+
#
|
30
|
+
# ActiveRecord::RuntimeRegistry.connection_handler
|
31
|
+
#
|
32
|
+
# returns a connection handler local to the current thread.
|
33
|
+
#
|
34
|
+
# This feature is accomplished by instantiating the class and storing the
|
35
|
+
# instance as a thread local keyed by the class name. In the example above
|
36
|
+
# a key "ActiveRecord::RuntimeRegistry" is stored in <tt>Thread.current</tt>.
|
37
|
+
# The class methods proxy to said thread local instance.
|
38
|
+
#
|
39
|
+
# If the class has an initializer, it must accept no arguments.
|
40
|
+
module PerThreadRegistry
|
41
|
+
def self.extended(object)
|
42
|
+
object.instance_variable_set "@per_thread_registry_key", object.name.freeze
|
43
|
+
end
|
44
|
+
|
45
|
+
def instance
|
46
|
+
Thread.current[@per_thread_registry_key] ||= new
|
47
|
+
end
|
48
|
+
|
49
|
+
protected
|
50
|
+
def method_missing(name, *args, &block) # :nodoc:
|
51
|
+
# Caches the method definition as a singleton method of the receiver.
|
52
|
+
#
|
53
|
+
# By letting #delegate handle it, we avoid an enclosure that'll capture args.
|
54
|
+
singleton_class.delegate name, to: :instance
|
55
|
+
|
56
|
+
send(name, *args, &block)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/lib/backports.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
module Neo4j
|
2
|
+
module ActiveNode
|
3
|
+
module Dependent
|
4
|
+
module AssociationMethods
|
5
|
+
def validate_dependent(value)
|
6
|
+
fail ArgumentError, "Invalid dependent value: #{value.inspect}" if not valid_dependent_value?(value)
|
7
|
+
end
|
8
|
+
|
9
|
+
def add_destroy_callbacks(model)
|
10
|
+
return if dependent.nil?
|
11
|
+
|
12
|
+
model.before_destroy(&method("dependent_#{dependent}_callback"))
|
13
|
+
rescue NameError
|
14
|
+
raise "Unknown dependent option #{dependent}"
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def valid_dependent_value?(value)
|
20
|
+
return true if value.nil?
|
21
|
+
|
22
|
+
self.respond_to?("dependent_#{value}_callback", true)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Callback methods
|
26
|
+
def dependent_delete_callback(object)
|
27
|
+
object.association_query_proxy(name).delete_all
|
28
|
+
end
|
29
|
+
|
30
|
+
def dependent_delete_orphans_callback(object)
|
31
|
+
object.as(:self).unique_nodes(self, :self, :n, :other_rel).query.delete(:n, :other_rel).exec
|
32
|
+
end
|
33
|
+
|
34
|
+
def dependent_destroy_callback(object)
|
35
|
+
unique_query = object.association_query_proxy(name)
|
36
|
+
unique_query.each_for_destruction(object, &:destroy) if unique_query
|
37
|
+
end
|
38
|
+
|
39
|
+
def dependent_destroy_orphans_callback(object)
|
40
|
+
unique_query = object.as(:self).unique_nodes(self, :self, :n, :other_rel)
|
41
|
+
unique_query.each_for_destruction(object, &:destroy) if unique_query
|
42
|
+
end
|
43
|
+
|
44
|
+
# End callback methods
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Neo4j
|
2
|
+
module ActiveNode
|
3
|
+
module Dependent
|
4
|
+
# methods used to resolve association dependencies
|
5
|
+
module QueryProxyMethods
|
6
|
+
# Used as part of `dependent: :destroy` and may not have any utility otherwise.
|
7
|
+
# It keeps track of the node responsible for a cascading `destroy` process.
|
8
|
+
# @param owning_node [#dependent_children] source_object The node that called this method. Typically, we would use QueryProxy's `source_object` method
|
9
|
+
# but this is not always available, so we require it explicitly.
|
10
|
+
def each_for_destruction(owning_node)
|
11
|
+
target = owning_node.called_by || owning_node
|
12
|
+
objects = pluck(identity).compact.reject do |obj|
|
13
|
+
target.dependent_children.include?(obj)
|
14
|
+
end
|
15
|
+
|
16
|
+
objects.each do |obj|
|
17
|
+
obj.called_by = target
|
18
|
+
target.dependent_children << obj
|
19
|
+
yield obj
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# This will match nodes who only have a single relationship of a given type.
|
24
|
+
# It's used by `dependent: :delete_orphans` and `dependent: :destroy_orphans` and may not have much utility otherwise.
|
25
|
+
# @param [Neo4j::ActiveNode::HasN::Association] association The Association object used throughout the match.
|
26
|
+
# @param [String, Symbol] other_node The identifier to use for the other end of the chain.
|
27
|
+
# @param [String, Symbol] other_rel The identifier to use for the relationship in the optional match.
|
28
|
+
# @return [Neo4j::ActiveNode::Query::QueryProxy]
|
29
|
+
def unique_nodes(association, self_identifer, other_node, other_rel)
|
30
|
+
fail 'Only supported by in QueryProxy chains started by an instance' unless source_object
|
31
|
+
return false if send(association.name).empty?
|
32
|
+
unique_nodes_query(association, self_identifer, other_node, other_rel)
|
33
|
+
.proxy_as(association.target_class, other_node)
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def unique_nodes_query(association, self_identifer, other_node, other_rel)
|
39
|
+
query.with(identity).proxy_as_optional(source_object.class, self_identifer)
|
40
|
+
.send(association.name, other_node, other_rel)
|
41
|
+
.query
|
42
|
+
.with(other_node)
|
43
|
+
.match("()#{association.arrow_cypher(:orphan_rel)}(#{other_node})")
|
44
|
+
.with(other_node, count: 'count(*)')
|
45
|
+
.where('count = {one}', one: 1)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Neo4j::ActiveNode
|
2
|
+
module Enum
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
include Neo4j::Shared::Enum
|
5
|
+
|
6
|
+
module ClassMethods
|
7
|
+
protected
|
8
|
+
|
9
|
+
def build_property_options(enum_keys, options = {})
|
10
|
+
if options[:_index]
|
11
|
+
super.merge!(index: :exact)
|
12
|
+
else
|
13
|
+
super
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def define_enum_methods(property_name, enum_keys, options)
|
18
|
+
super
|
19
|
+
define_enum_scopes(property_name, enum_keys)
|
20
|
+
end
|
21
|
+
|
22
|
+
def define_enum_scopes(property_name, enum_keys)
|
23
|
+
enum_keys.keys.each do |name|
|
24
|
+
scope name, -> { where(property_name => name) }
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Neo4j::ActiveNode::HasN
|
2
|
+
class Association
|
3
|
+
class RelFactory
|
4
|
+
[:start_object, :other_node_or_nodes, :properties, :association].tap do |accessors|
|
5
|
+
attr_reader(*accessors)
|
6
|
+
private(*accessors)
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.create(start_object, other_node_or_nodes, properties, association)
|
10
|
+
factory = new(start_object, other_node_or_nodes, properties, association)
|
11
|
+
factory._create_relationship
|
12
|
+
end
|
13
|
+
|
14
|
+
def _create_relationship
|
15
|
+
creator = association.relationship_class ? :rel_class : :factory
|
16
|
+
send(:"_create_relationship_with_#{creator}")
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def initialize(start_object, other_node_or_nodes, properties, association)
|
22
|
+
@start_object = start_object
|
23
|
+
@other_node_or_nodes = other_node_or_nodes
|
24
|
+
@properties = properties
|
25
|
+
@association = association
|
26
|
+
end
|
27
|
+
|
28
|
+
def _create_relationship_with_rel_class
|
29
|
+
Array(other_node_or_nodes).each do |other_node|
|
30
|
+
node_props = _nodes_for_create(other_node, :from_node, :to_node)
|
31
|
+
association.relationship_class.create!(properties.merge(node_props))
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def _create_relationship_with_factory
|
36
|
+
Array(other_node_or_nodes).each do |other_node|
|
37
|
+
wrapper = _rel_wrapper(properties)
|
38
|
+
base = _match_query(other_node, wrapper)
|
39
|
+
factory = Neo4j::Shared::RelQueryFactory.new(wrapper, wrapper.rel_identifier)
|
40
|
+
factory.base_query = base
|
41
|
+
factory.query.exec
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def _match_query(other_node, wrapper)
|
46
|
+
nodes = _nodes_for_create(other_node, wrapper.from_node_identifier, wrapper.to_node_identifier)
|
47
|
+
Neo4j::Session.current.query.match_nodes(nodes)
|
48
|
+
end
|
49
|
+
|
50
|
+
def _nodes_for_create(other_node, from_node_id, to_node_id)
|
51
|
+
nodes = [@start_object, other_node]
|
52
|
+
nodes.reverse! if association.direction == :in
|
53
|
+
{from_node_id => nodes[0], to_node_id => nodes[1]}
|
54
|
+
end
|
55
|
+
|
56
|
+
def _rel_wrapper(properties)
|
57
|
+
Neo4j::ActiveNode::HasN::Association::RelWrapper.new(association, properties)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class Neo4j::ActiveNode::HasN::Association
|
2
|
+
# Provides the interface needed to interact with the ActiveRel query factory.
|
3
|
+
class RelWrapper
|
4
|
+
include Neo4j::Shared::Cypher::RelIdentifiers
|
5
|
+
include Neo4j::Shared::Cypher::CreateMethod
|
6
|
+
|
7
|
+
attr_reader :type, :association
|
8
|
+
attr_accessor :properties
|
9
|
+
private :association
|
10
|
+
alias_method :props_for_create, :properties
|
11
|
+
|
12
|
+
def initialize(association, properties = {})
|
13
|
+
@association = association
|
14
|
+
@properties = properties
|
15
|
+
@type = association.relationship_type(true)
|
16
|
+
creates_unique(association.creates_unique_option) if association.unique?
|
17
|
+
end
|
18
|
+
|
19
|
+
def persisted?
|
20
|
+
false
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|