neo4j 1.0.0.beta.20 → 3.0.0.alpha.2
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 +7 -0
- data/CHANGELOG +243 -0
- data/CONTRIBUTORS +12 -0
- data/Gemfile +10 -11
- data/README.md +23 -0
- data/bin/neo4j-jars +33 -0
- data/config/locales/en.yml +5 -0
- data/config/neo4j/config.yml +98 -0
- data/lib/neo4j.rb +28 -68
- data/lib/neo4j/active_node.rb +60 -0
- data/lib/neo4j/active_node/callbacks.rb +41 -0
- data/lib/neo4j/active_node/has_n.rb +138 -0
- data/lib/neo4j/active_node/has_n/decl_rel.rb +236 -0
- data/lib/neo4j/active_node/has_n/nodes.rb +82 -0
- data/lib/neo4j/active_node/identity.rb +28 -0
- data/lib/neo4j/active_node/initialize.rb +24 -0
- data/lib/neo4j/active_node/labels.rb +142 -0
- data/lib/neo4j/active_node/persistence.rb +193 -0
- data/lib/neo4j/active_node/property.rb +41 -0
- data/lib/neo4j/active_node/rels.rb +11 -0
- data/lib/neo4j/active_node/validations.rb +51 -0
- data/lib/neo4j/railtie.rb +40 -0
- data/lib/neo4j/version.rb +1 -1
- data/lib/neo4j/wrapper.rb +25 -0
- data/neo4j.gemspec +25 -15
- metadata +136 -149
- data/README.rdoc +0 -135
- data/lib/generators/neo4j.rb +0 -65
- data/lib/generators/neo4j/model/model_generator.rb +0 -39
- data/lib/generators/neo4j/model/templates/model.erb +0 -7
- data/lib/neo4j/config.rb +0 -153
- data/lib/neo4j/database.rb +0 -56
- data/lib/neo4j/equal.rb +0 -21
- data/lib/neo4j/event_handler.rb +0 -116
- data/lib/neo4j/index/class_methods.rb +0 -62
- data/lib/neo4j/index/index.rb +0 -33
- data/lib/neo4j/index/indexer.rb +0 -312
- data/lib/neo4j/index/indexer_registry.rb +0 -68
- data/lib/neo4j/index/lucene_query.rb +0 -191
- data/lib/neo4j/jars/geronimo-jta_1.1_spec-1.1.1.jar +0 -0
- data/lib/neo4j/jars/lucene-core-3.0.2.jar +0 -0
- data/lib/neo4j/jars/neo4j-index-1.2-1.2.M03.jar +0 -0
- data/lib/neo4j/jars/neo4j-kernel-1.2-1.2.M03.jar +0 -0
- data/lib/neo4j/jars/neo4j-lucene-index-0.2-1.2.M03.jar +0 -0
- data/lib/neo4j/load.rb +0 -21
- data/lib/neo4j/mapping/class_methods/init_node.rb +0 -50
- data/lib/neo4j/mapping/class_methods/init_rel.rb +0 -35
- data/lib/neo4j/mapping/class_methods/property.rb +0 -80
- data/lib/neo4j/mapping/class_methods/relationship.rb +0 -90
- data/lib/neo4j/mapping/class_methods/root.rb +0 -31
- data/lib/neo4j/mapping/class_methods/rule.rb +0 -295
- data/lib/neo4j/mapping/decl_relationship_dsl.rb +0 -214
- data/lib/neo4j/mapping/has_n.rb +0 -83
- data/lib/neo4j/mapping/node_mixin.rb +0 -97
- data/lib/neo4j/mapping/relationship_mixin.rb +0 -117
- data/lib/neo4j/model.rb +0 -4
- data/lib/neo4j/neo4j.rb +0 -95
- data/lib/neo4j/node.rb +0 -131
- data/lib/neo4j/node_mixin.rb +0 -4
- data/lib/neo4j/node_relationship.rb +0 -149
- data/lib/neo4j/node_traverser.rb +0 -157
- data/lib/neo4j/property.rb +0 -111
- data/lib/neo4j/rails/finders.rb +0 -121
- data/lib/neo4j/rails/lucene_connection_closer.rb +0 -19
- data/lib/neo4j/rails/mapping/property.rb +0 -35
- data/lib/neo4j/rails/model.rb +0 -324
- data/lib/neo4j/rails/railtie.rb +0 -16
- data/lib/neo4j/rails/transaction.rb +0 -67
- data/lib/neo4j/rails/tx_methods.rb +0 -15
- data/lib/neo4j/rails/validations/non_nil.rb +0 -11
- data/lib/neo4j/rails/validations/uniqueness.rb +0 -31
- data/lib/neo4j/rails/value.rb +0 -124
- data/lib/neo4j/rails/value_properties.rb +0 -29
- data/lib/neo4j/relationship.rb +0 -169
- data/lib/neo4j/relationship_mixin.rb +0 -4
- data/lib/neo4j/relationship_traverser.rb +0 -92
- data/lib/neo4j/to_java.rb +0 -31
- data/lib/neo4j/transaction.rb +0 -68
- data/lib/neo4j/type_converters.rb +0 -98
data/lib/neo4j.rb
CHANGED
@@ -1,70 +1,30 @@
|
|
1
|
-
include Java
|
2
|
-
|
3
|
-
require 'enumerator'
|
4
|
-
require 'forwardable'
|
5
|
-
require 'time'
|
6
|
-
require 'date'
|
7
|
-
|
8
|
-
require 'neo4j/jars/neo4j-index-1.2-1.2.M03.jar'
|
9
|
-
require 'neo4j/jars/neo4j-kernel-1.2-1.2.M03.jar'
|
10
|
-
require 'neo4j/jars/neo4j-lucene-index-0.2-1.2.M03.jar'
|
11
|
-
require 'neo4j/jars/geronimo-jta_1.1_spec-1.1.1.jar'
|
12
|
-
require 'neo4j/jars/lucene-core-3.0.2.jar'
|
13
|
-
require 'neo4j/to_java'
|
14
1
|
require 'neo4j/version'
|
15
|
-
require 'neo4j/equal'
|
16
|
-
|
17
|
-
require 'neo4j/event_handler'
|
18
|
-
require 'neo4j/database'
|
19
|
-
require 'neo4j/neo4j'
|
20
|
-
|
21
|
-
require 'neo4j/index/index'
|
22
|
-
require 'neo4j/index/class_methods'
|
23
|
-
require 'neo4j/index/indexer_registry'
|
24
|
-
require 'neo4j/index/indexer'
|
25
|
-
require 'neo4j/index/lucene_query'
|
26
|
-
require 'neo4j/relationship_traverser'
|
27
|
-
require 'neo4j/node_traverser'
|
28
|
-
require 'neo4j/property'
|
29
|
-
require 'neo4j/transaction'
|
30
|
-
require 'neo4j/node_relationship'
|
31
|
-
require 'neo4j/load'
|
32
|
-
require 'neo4j/relationship'
|
33
|
-
require 'neo4j/node'
|
34
|
-
require 'neo4j/config'
|
35
|
-
require 'neo4j/type_converters'
|
36
|
-
require 'neo4j/mapping/class_methods/init_node'
|
37
|
-
require 'neo4j/mapping/class_methods/init_rel'
|
38
|
-
require 'neo4j/mapping/class_methods/root'
|
39
|
-
require 'neo4j/mapping/class_methods/property'
|
40
|
-
require 'neo4j/mapping/class_methods/relationship'
|
41
|
-
require 'neo4j/mapping/decl_relationship_dsl'
|
42
|
-
require 'neo4j/mapping/has_n'
|
43
|
-
require 'neo4j/mapping/node_mixin'
|
44
|
-
require 'neo4j/mapping/relationship_mixin'
|
45
|
-
require 'neo4j/node_mixin'
|
46
|
-
require 'neo4j/relationship_mixin'
|
47
|
-
require 'neo4j/mapping/class_methods/rule'
|
48
|
-
|
49
|
-
# rails
|
50
|
-
require 'rails/railtie'
|
51
|
-
require 'active_model'
|
52
|
-
require 'neo4j/rails/tx_methods'
|
53
|
-
require 'neo4j/rails/transaction'
|
54
|
-
require 'neo4j/rails/railtie'
|
55
|
-
require 'neo4j/rails/validations/uniqueness'
|
56
|
-
require 'neo4j/rails/validations/non_nil'
|
57
|
-
require 'neo4j/rails/finders'
|
58
|
-
require 'neo4j/rails/mapping/property'
|
59
|
-
require 'neo4j/rails/model'
|
60
|
-
require 'neo4j/rails/value_properties'
|
61
|
-
require 'neo4j/rails/value'
|
62
|
-
require 'neo4j/rails/lucene_connection_closer'
|
63
|
-
|
64
|
-
require 'neo4j/model'
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
# hmm, looks like Enumerator have been moved in some ruby versions
|
69
|
-
Enumerator = Enumerable::Enumerator unless defined? Enumerator
|
70
2
|
|
3
|
+
#require "delegate"
|
4
|
+
#require "time"
|
5
|
+
#require "set"
|
6
|
+
#
|
7
|
+
#require "active_support/core_ext"
|
8
|
+
#require "active_support/json"
|
9
|
+
#require "active_support/inflector"
|
10
|
+
#require "active_support/time_with_zone"
|
11
|
+
|
12
|
+
require "neo4j-core"
|
13
|
+
require "active_model"
|
14
|
+
require 'active_support/concern'
|
15
|
+
require 'active_support/core_ext/class/attribute.rb'
|
16
|
+
|
17
|
+
require 'active_attr'
|
18
|
+
require 'neo4j/wrapper'
|
19
|
+
require "neo4j/active_node/labels"
|
20
|
+
require 'neo4j/active_node/identity'
|
21
|
+
require 'neo4j/active_node/callbacks'
|
22
|
+
require 'neo4j/active_node/initialize'
|
23
|
+
require 'neo4j/active_node/property'
|
24
|
+
require 'neo4j/active_node/persistence'
|
25
|
+
require 'neo4j/active_node/validations'
|
26
|
+
require 'neo4j/active_node/rels'
|
27
|
+
require 'neo4j/active_node/has_n'
|
28
|
+
require 'neo4j/active_node/has_n/decl_rel'
|
29
|
+
require 'neo4j/active_node/has_n/nodes'
|
30
|
+
require 'neo4j/active_node'
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Neo4j
|
2
|
+
|
3
|
+
# Makes Neo4j nodes and relationships behave like active record objects.
|
4
|
+
# By including this module in your class it will create a mapping for the node to your ruby class
|
5
|
+
# by using a Neo4j Label with the same name as the class. When the node is loaded from the database it
|
6
|
+
# will check if there is a ruby class for the labels it has.
|
7
|
+
# If there Ruby class with the same name as the label then the Neo4j node will be wrapped
|
8
|
+
# in a new object of that class.
|
9
|
+
#
|
10
|
+
# = ClassMethods
|
11
|
+
# * {Neo4j::ActiveNode::Labels::ClassMethods} defines methods like: <tt>index</tt> and <tt>find</tt>
|
12
|
+
# * {Neo4j::ActiveNode::Persistence::ClassMethods} defines methods like: <tt>create</tt> and <tt>create!</tt>
|
13
|
+
# * {Neo4j::ActiveNode::Property::ClassMethods} defines methods like: <tt>property</tt>.
|
14
|
+
#
|
15
|
+
# @example Create a Ruby wrapper for a Neo4j Node
|
16
|
+
# class Company
|
17
|
+
# include Neo4j::ActiveNode
|
18
|
+
# property :name
|
19
|
+
# end
|
20
|
+
# company = Company.new
|
21
|
+
# company.name = 'My Company AB'
|
22
|
+
# Company.save
|
23
|
+
#
|
24
|
+
module ActiveNode
|
25
|
+
extend ActiveSupport::Concern
|
26
|
+
extend ActiveModel::Naming
|
27
|
+
|
28
|
+
include ActiveModel::Conversion
|
29
|
+
include ActiveModel::Serializers::Xml
|
30
|
+
include ActiveModel::Serializers::JSON
|
31
|
+
include Neo4j::ActiveNode::Initialize
|
32
|
+
include Neo4j::ActiveNode::Identity
|
33
|
+
include Neo4j::ActiveNode::Persistence
|
34
|
+
include Neo4j::ActiveNode::Property
|
35
|
+
include Neo4j::ActiveNode::Labels
|
36
|
+
include Neo4j::ActiveNode::Callbacks
|
37
|
+
include Neo4j::ActiveNode::Validations
|
38
|
+
include Neo4j::ActiveNode::Rels
|
39
|
+
include Neo4j::ActiveNode::HasN
|
40
|
+
|
41
|
+
def wrapper
|
42
|
+
self
|
43
|
+
end
|
44
|
+
|
45
|
+
def neo4j_obj
|
46
|
+
_persisted_node || raise("Tried to access native neo4j object on a none persisted object")
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
included do
|
51
|
+
def self.inherited(other)
|
52
|
+
attributes.each_pair do |k,v|
|
53
|
+
other.attributes[k] = v
|
54
|
+
end
|
55
|
+
Neo4j::ActiveNode::Labels.add_wrapped_class(other)
|
56
|
+
super
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Neo4j
|
2
|
+
module ActiveNode
|
3
|
+
module Callbacks #:nodoc:
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
module ClassMethods
|
7
|
+
include ActiveModel::Callbacks
|
8
|
+
end
|
9
|
+
|
10
|
+
included do
|
11
|
+
include ActiveModel::Validations::Callbacks
|
12
|
+
|
13
|
+
define_model_callbacks :initialize, :find, :only => :after
|
14
|
+
define_model_callbacks :save, :create, :update, :destroy
|
15
|
+
end
|
16
|
+
|
17
|
+
def destroy #:nodoc:
|
18
|
+
run_callbacks(:destroy) { super }
|
19
|
+
end
|
20
|
+
|
21
|
+
def touch(*) #:nodoc:
|
22
|
+
run_callbacks(:touch) { super }
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def create_or_update #:nodoc:
|
28
|
+
run_callbacks(:save) { super }
|
29
|
+
end
|
30
|
+
|
31
|
+
def create_model #:nodoc:
|
32
|
+
run_callbacks(:create) { super }
|
33
|
+
end
|
34
|
+
|
35
|
+
def update_model(*) #:nodoc:
|
36
|
+
run_callbacks(:update) { super }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
module Neo4j::ActiveNode
|
2
|
+
module HasN
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
def _decl_rels_for(rel_type)
|
6
|
+
self.class._decl_rels[rel_type]
|
7
|
+
end
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
|
11
|
+
def _decl_rels
|
12
|
+
@_decl_rels ||= {}
|
13
|
+
end
|
14
|
+
|
15
|
+
# make sure the inherited classes inherit the <tt>_decl_rels</tt> hash
|
16
|
+
def inherited(klass)
|
17
|
+
copy = _decl_rels.clone
|
18
|
+
copy.each_pair { |k, v| copy[k] = v.inherit_new }
|
19
|
+
klass.instance_variable_set(:@_decl_rels, copy)
|
20
|
+
super
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
# Specifies a relationship between two node active node classes.
|
25
|
+
# Generates assignment and accessor methods for the given relationship.
|
26
|
+
# Both incoming and outgoing relationships can be declared, see {Neo4j::ActiveNode::HasN::DeclRel}
|
27
|
+
#
|
28
|
+
# @example has_n(:files)
|
29
|
+
#
|
30
|
+
# class FolderNode
|
31
|
+
# include Neo4j::ActiveNode
|
32
|
+
# has_n(:files)
|
33
|
+
# end
|
34
|
+
#
|
35
|
+
# folder = FolderNode.new
|
36
|
+
# folder.files << Neo4j::Node.new << Neo4j::Node.new
|
37
|
+
# folder.files.inject {...}
|
38
|
+
#
|
39
|
+
# FolderNode.files #=> 'files' the name of the relationship
|
40
|
+
#
|
41
|
+
# @example has_n(x).to(...)
|
42
|
+
#
|
43
|
+
# # You can declare which class it has relationship to.
|
44
|
+
# # The generated relationships will be prefixed with the name of that class.
|
45
|
+
# class FolderNode
|
46
|
+
# include Neo4j::ActiveNode
|
47
|
+
# has_n(:files).to(File)
|
48
|
+
# # Same as has_n(:files).to("File")
|
49
|
+
# end
|
50
|
+
#
|
51
|
+
# FolderNode.files #=> 'File#files' the name of the relationship
|
52
|
+
#
|
53
|
+
# @example has_n(x).from(class, has_n_name)
|
54
|
+
#
|
55
|
+
# # generate accessor method for traversing and adding relationship on incoming nodes.
|
56
|
+
# class FileNode
|
57
|
+
# include Neo4j::ActiveNode
|
58
|
+
# has_one(:folder).from(FolderNode.files)
|
59
|
+
# # or same as
|
60
|
+
# has_one(:folder).from(FolderNode, :files)
|
61
|
+
# end
|
62
|
+
#
|
63
|
+
#
|
64
|
+
# @return [Neo4j::ActiveNode::HasN::DeclRel] a DSL object where the has_n relationship can be further specified
|
65
|
+
def has_n(rel_type)
|
66
|
+
clazz = self
|
67
|
+
module_eval(%Q{
|
68
|
+
def #{rel_type}()
|
69
|
+
dsl = _decl_rels_for('#{rel_type}'.to_sym)
|
70
|
+
Neo4j::ActiveNode::HasN::Nodes.new(self, dsl)
|
71
|
+
end}, __FILE__, __LINE__)
|
72
|
+
|
73
|
+
|
74
|
+
module_eval(%Q{
|
75
|
+
def #{rel_type}_rels
|
76
|
+
dsl = _decl_rels_for('#{rel_type}'.to_sym)
|
77
|
+
dsl.all_relationships(self)
|
78
|
+
end}, __FILE__, __LINE__)
|
79
|
+
|
80
|
+
instance_eval(%Q{
|
81
|
+
def #{rel_type}
|
82
|
+
_decl_rels[:#{rel_type}].rel_type
|
83
|
+
end}, __FILE__, __LINE__)
|
84
|
+
|
85
|
+
_decl_rels[rel_type.to_sym] = DeclRel.new(rel_type, false, clazz)
|
86
|
+
end
|
87
|
+
|
88
|
+
|
89
|
+
# Specifies a relationship between two node classes.
|
90
|
+
# Generates assignment and accessor methods for the given relationship
|
91
|
+
# Old relationship is deleted when a new relationship is assigned.
|
92
|
+
# Both incoming and outgoing relationships can be declared, see {Neo4j::Wrapper::HasN::DeclRel}
|
93
|
+
#
|
94
|
+
# @example
|
95
|
+
#
|
96
|
+
# class FileNode
|
97
|
+
# include Neo4j::ActiveNode
|
98
|
+
# has_one(:folder)
|
99
|
+
# end
|
100
|
+
#
|
101
|
+
# file = FileNode.create
|
102
|
+
# file.folder = Neo4j::Node.create
|
103
|
+
# file.folder # => the node above
|
104
|
+
# file.folder_rel # => the relationship object between those nodes
|
105
|
+
#
|
106
|
+
# @return [Neo4j::ActiveNode::HasN::DeclRel] a DSL object where the has_one relationship can be futher specified
|
107
|
+
def has_one(rel_type)
|
108
|
+
clazz = self
|
109
|
+
module_eval(%Q{def #{rel_type}=(value)
|
110
|
+
dsl = _decl_rels_for(:#{rel_type})
|
111
|
+
rel = dsl.single_relationship(self)
|
112
|
+
rel && rel.del
|
113
|
+
dsl.create_relationship_to(self, value) if value
|
114
|
+
end}, __FILE__, __LINE__)
|
115
|
+
|
116
|
+
module_eval(%Q{def #{rel_type}
|
117
|
+
dsl = _decl_rels_for('#{rel_type}'.to_sym)
|
118
|
+
dsl.single_node(self)
|
119
|
+
end}, __FILE__, __LINE__)
|
120
|
+
|
121
|
+
module_eval(%Q{def #{rel_type}_rel
|
122
|
+
dsl = _decl_rels_for(:#{rel_type})
|
123
|
+
dsl.single_relationship(self)
|
124
|
+
end}, __FILE__, __LINE__)
|
125
|
+
|
126
|
+
instance_eval(%Q{
|
127
|
+
def #{rel_type}
|
128
|
+
_decl_rels[:#{rel_type}].rel_type
|
129
|
+
end}, __FILE__, __LINE__)
|
130
|
+
|
131
|
+
_decl_rels[rel_type.to_sym] = DeclRel.new(rel_type, true, clazz)
|
132
|
+
end
|
133
|
+
|
134
|
+
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
@@ -0,0 +1,236 @@
|
|
1
|
+
module Neo4j
|
2
|
+
module ActiveNode
|
3
|
+
module HasN
|
4
|
+
|
5
|
+
|
6
|
+
# A DSL for declared relationships has_n and has_one
|
7
|
+
# This DSL will be used to create accessor methods for relationships.
|
8
|
+
# Instead of using the 'raw' Neo4j::ActiveNode#rels method where one needs to know
|
9
|
+
# the name of relationship and direction one can use the generated accessor methods.
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
#
|
13
|
+
# class Folder
|
14
|
+
# include Neo4j::ActiveNode
|
15
|
+
# property :name
|
16
|
+
# # Declaring a Many relationship to any other node
|
17
|
+
# has_n(:files)
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# class File
|
21
|
+
# include Neo4j::ActiveNode
|
22
|
+
# # declaring a incoming relationship from Folder's relationship files
|
23
|
+
# has_one(:folder).from(Folder, :files)
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# The following methods will be generated:
|
27
|
+
# <b>Folder#files</b> :: returns an Enumerable of outgoing nodes for relationship 'files'
|
28
|
+
# <b>Folder#files_rels</b> :: returns an Enumerable of outgoing relationships for relationship 'files'
|
29
|
+
# <b>File#folder</b> :: for adding one node for the relationship 'files' from the outgoing Folder node
|
30
|
+
# <b>File#folder_rel</b> :: for accessing relationship 'files' from the outgoing Folder node
|
31
|
+
# <b>File#folder</b> :: for accessing nodes from relationship 'files' from the outgoing Folder node
|
32
|
+
#
|
33
|
+
class DeclRel
|
34
|
+
attr_reader :source_class, :dir, :rel_type, :method_id
|
35
|
+
|
36
|
+
def initialize(method_id, has_one, source_class)
|
37
|
+
@method_id = method_id
|
38
|
+
@has_one = has_one
|
39
|
+
@dir = :outgoing
|
40
|
+
@rel_type = method_id.to_sym
|
41
|
+
@source_class = source_class
|
42
|
+
end
|
43
|
+
|
44
|
+
def inherit_new
|
45
|
+
base = self
|
46
|
+
dr = DeclRel.new(@method_id, @has_one, @source_class)
|
47
|
+
dr.instance_eval do
|
48
|
+
@dir = base.dir
|
49
|
+
@rel_type = base.rel_type
|
50
|
+
@target_name = base.target_name if base.target_name
|
51
|
+
@source_class = base.source_class
|
52
|
+
end
|
53
|
+
dr
|
54
|
+
end
|
55
|
+
|
56
|
+
def to_s
|
57
|
+
"DeclRel #{object_id} dir: #{@dir} rel_id: #{@method_id}, rel_type: #{@rel_type}, target_class:#{@target_name}"
|
58
|
+
end
|
59
|
+
|
60
|
+
# @return [true, false]
|
61
|
+
def has_one?
|
62
|
+
@has_one
|
63
|
+
end
|
64
|
+
|
65
|
+
# @return [true, false]
|
66
|
+
def has_n?
|
67
|
+
!@has_one
|
68
|
+
end
|
69
|
+
|
70
|
+
# @return [true,false]
|
71
|
+
def incoming? #:nodoc:
|
72
|
+
@dir == :incoming
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
# Declares an outgoing relationship type.
|
77
|
+
# It is possible to prefix relationship types so that it's possible to distinguish different incoming relationships.
|
78
|
+
# There is no validation that the added node is of the specified class.
|
79
|
+
#
|
80
|
+
# @example Example
|
81
|
+
# class FolderNode
|
82
|
+
# include Neo4j::ActiveNode
|
83
|
+
# has_n(:files).to(FileNode)
|
84
|
+
# has_one(:root).to("FileSystem") # also possible, if the class is not defined yet
|
85
|
+
# end
|
86
|
+
#
|
87
|
+
# folder = FolderNode.new
|
88
|
+
# # generate a relationship between folder and file of type 'FileNode#files'
|
89
|
+
# folder.files << FileNode.new
|
90
|
+
#
|
91
|
+
# @example relationship with a hash, user defined relationship
|
92
|
+
#
|
93
|
+
# class FolderNode
|
94
|
+
# include Neo4j::ActiveNode
|
95
|
+
# has_n(:files).to('FolderNode#files')
|
96
|
+
# end
|
97
|
+
#
|
98
|
+
# @example without prefix
|
99
|
+
#
|
100
|
+
# class FolderNode
|
101
|
+
# include Neo4j::ActiveNode
|
102
|
+
# has_n(:files).to(:contains)
|
103
|
+
# end
|
104
|
+
#
|
105
|
+
# file = FileNode.new
|
106
|
+
# # create an outgoing relationship of type 'contains' from folder node to file
|
107
|
+
# folder.files << FolderNode.new
|
108
|
+
#
|
109
|
+
# @param [Class, String, Symbol] target the other class to which this relationship goes (if String or Class) or the relationship (if Symbol)
|
110
|
+
# @param [String, Symbol] rel_type the rel_type postfix for the relationships, which defaults to the same as the has_n/one method id
|
111
|
+
# @return self
|
112
|
+
def to(target, rel_type = @method_id)
|
113
|
+
@dir = :outgoing
|
114
|
+
|
115
|
+
case target
|
116
|
+
when /#/
|
117
|
+
@target_name, _ = target.to_s.split("#")
|
118
|
+
@rel_type = target.to_sym
|
119
|
+
when Class, String
|
120
|
+
@target_name = target.to_s
|
121
|
+
@rel_type = "#{@source_class}##{rel_type}".to_sym
|
122
|
+
when Symbol
|
123
|
+
@target_name = nil
|
124
|
+
@rel_type = target.to_sym
|
125
|
+
else
|
126
|
+
raise "Expected a class or a symbol for, got #{target}/#{target.class}"
|
127
|
+
end
|
128
|
+
self
|
129
|
+
end
|
130
|
+
|
131
|
+
# Specifies an incoming relationship.
|
132
|
+
# Will use the outgoing relationship given by the from class.
|
133
|
+
#
|
134
|
+
# @example with prefix FileNode
|
135
|
+
# class FolderNode
|
136
|
+
# include Neo4j::NodeMixin
|
137
|
+
# has_n(:files).to(FileNode)
|
138
|
+
# end
|
139
|
+
#
|
140
|
+
# class FileNode
|
141
|
+
# include Neo4j::NodeMixin
|
142
|
+
# # will only traverse any incoming relationship of type files from node FileNode
|
143
|
+
# has_one(:folder).from(FolderNode.files)
|
144
|
+
# # alternative: has_one(:folder).from(FolderNode, :files)
|
145
|
+
# end
|
146
|
+
#
|
147
|
+
# file = FileNode.new
|
148
|
+
# # create an outgoing relationship of type 'FileNode#files' from folder node to file (FileNode is the prefix).
|
149
|
+
# file.folder = FolderNode.new
|
150
|
+
#
|
151
|
+
# @example without prefix
|
152
|
+
#
|
153
|
+
# class FolderNode
|
154
|
+
# include Neo4j::NodeMixin
|
155
|
+
# has_n(:files)
|
156
|
+
# end
|
157
|
+
#
|
158
|
+
# class FileNode
|
159
|
+
# include Neo4j::NodeMixin
|
160
|
+
# has_one(:folder).from(:files) # will traverse any incoming relationship of type files
|
161
|
+
# end
|
162
|
+
#
|
163
|
+
# file = FileNode.new
|
164
|
+
# # create an outgoing relationship of type 'files' from folder node to file
|
165
|
+
# file.folder = FolderNode.new
|
166
|
+
#
|
167
|
+
#
|
168
|
+
def from(target, rel_type=@method_id)
|
169
|
+
@dir = :incoming
|
170
|
+
|
171
|
+
case target
|
172
|
+
when /#/
|
173
|
+
@target_name, _ = target.to_s.split("#")
|
174
|
+
@rel_type = target
|
175
|
+
when Class, String
|
176
|
+
@target_name = target.to_s
|
177
|
+
@rel_type = "#{@target_name}##{rel_type}".to_sym
|
178
|
+
when Symbol
|
179
|
+
@target_name = nil
|
180
|
+
@rel_type = target.to_sym
|
181
|
+
else
|
182
|
+
raise "Expected a class or a symbol for, got #{target}/#{target.class}"
|
183
|
+
end
|
184
|
+
self
|
185
|
+
end
|
186
|
+
|
187
|
+
|
188
|
+
# @private
|
189
|
+
def target_name
|
190
|
+
@target_name
|
191
|
+
end
|
192
|
+
|
193
|
+
def target_class
|
194
|
+
@target_name && @target_name.split("::").inject(Kernel) { |container, name| container.const_get(name.to_s) }
|
195
|
+
end
|
196
|
+
|
197
|
+
|
198
|
+
# @private
|
199
|
+
def each_node(node, &block)
|
200
|
+
node.nodes(dir: dir, type: rel_type).each { |n| block.call(n)}
|
201
|
+
end
|
202
|
+
|
203
|
+
def all_relationships(node)
|
204
|
+
# TODO fix ruby warning - warning: Enumerator.new without a block is deprecated; use Object#to_enum
|
205
|
+
Enumerator.new(self, :each_rel, node)
|
206
|
+
end
|
207
|
+
|
208
|
+
def each_rel(node, &block) #:nodoc:
|
209
|
+
node.rels(dir: dir, type: rel_type).each { |rel| block.call(rel) }
|
210
|
+
end
|
211
|
+
|
212
|
+
def single_relationship(node)
|
213
|
+
node.rel(dir: dir, type: rel_type)
|
214
|
+
end
|
215
|
+
|
216
|
+
def single_node(node)
|
217
|
+
node.node(dir: dir, type: rel_type)
|
218
|
+
end
|
219
|
+
|
220
|
+
# @private
|
221
|
+
def _each_node(node, &block) #:nodoc:
|
222
|
+
node._rels(dir: dir, type: rel_type).each do |rel|
|
223
|
+
block.call rel._other_node(node)
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
# @private
|
228
|
+
def create_relationship_to(node, other) # :nodoc:
|
229
|
+
from, to = incoming? ? [other, node] : [node, other]
|
230
|
+
from.create_rel(@rel_type, to)
|
231
|
+
end
|
232
|
+
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|