neo4j 1.0.0-java → 1.1.0.beta.1-java
Sign up to get free protection for your applications and to get access to all the features.
- data/CONTRIBUTORS +1 -0
- data/Gemfile +1 -0
- data/README.rdoc +1 -0
- data/lib/neo4j/algo/algo.rb +5 -5
- data/lib/neo4j/database.rb +1 -1
- data/lib/neo4j/has_n/class_methods.rb +5 -6
- data/lib/neo4j/has_n/decl_relationship_dsl.rb +32 -21
- data/lib/neo4j/has_n/mapping.rb +4 -5
- data/lib/neo4j/index/indexer.rb +21 -17
- data/lib/neo4j/index/indexer_registry.rb +1 -0
- data/lib/neo4j/index/lucene_query.rb +1 -1
- data/lib/neo4j/jars/core/neo4j-backup-1.3.jar +0 -0
- data/lib/neo4j/jars/core/{neo4j-graph-algo-1.3.M03.jar → neo4j-graph-algo-1.3.jar} +0 -0
- data/lib/neo4j/jars/core/neo4j-kernel-1.3.jar +0 -0
- data/lib/neo4j/jars/core/neo4j-lucene-index-1.3.jar +0 -0
- data/lib/neo4j/jars/ha/neo4j-com-1.3.jar +0 -0
- data/lib/neo4j/jars/ha/neo4j-ha-1.3.jar +0 -0
- data/lib/neo4j/jars/ha/neo4j-jmx-1.3.jar +0 -0
- data/lib/neo4j/jars/ha/neo4j-management-1.3.jar +0 -0
- data/lib/neo4j/jars/ha/{neo4j-shell-1.3.M03.jar → neo4j-shell-1.3.jar} +0 -0
- data/lib/neo4j/neo4j.rb +1 -1
- data/lib/neo4j/node.rb +2 -3
- data/lib/neo4j/node_mixin/node_mixin.rb +5 -0
- data/lib/neo4j/property/class_methods.rb +6 -10
- data/lib/neo4j/property/property.rb +0 -2
- data/lib/neo4j/rails/attributes.rb +10 -8
- data/lib/neo4j/rails/callbacks.rb +1 -1
- data/lib/neo4j/rails/finders.rb +1 -1
- data/lib/neo4j/rails/lucene_connection_closer.rb +1 -3
- data/lib/neo4j/rails/mapping/property.rb +112 -35
- data/lib/neo4j/rails/model.rb +10 -0
- data/lib/neo4j/rails/persistence.rb +10 -4
- data/lib/neo4j/rails/rails.rb +6 -2
- data/lib/neo4j/rails/rel_persistence.rb +231 -0
- data/lib/neo4j/rails/relationship.rb +126 -0
- data/lib/neo4j/rails/relationships/node_dsl.rb +91 -0
- data/lib/neo4j/rails/relationships/relationships.rb +47 -40
- data/lib/neo4j/rails/relationships/rels_dsl.rb +82 -0
- data/lib/neo4j/rails/relationships/storage.rb +161 -0
- data/lib/neo4j/rails/serialization.rb +1 -1
- data/lib/neo4j/rails/validations/associated.rb +53 -0
- data/lib/neo4j/rails/validations.rb +2 -3
- data/lib/neo4j/relationship.rb +3 -3
- data/lib/neo4j/relationship_mixin/relationship_mixin.rb +5 -1
- data/lib/neo4j/rels/traverser.rb +12 -12
- data/lib/neo4j/rule/rule_node.rb +2 -1
- data/lib/neo4j/to_java.rb +0 -4
- data/lib/neo4j/traversal/traverser.rb +24 -3
- data/lib/neo4j/type_converters/type_converters.rb +59 -6
- data/lib/neo4j/version.rb +1 -1
- data/lib/neo4j.rb +10 -8
- metadata +21 -16
- data/lib/neo4j/jars/core/neo4j-backup-1.3.M03.jar +0 -0
- data/lib/neo4j/jars/core/neo4j-kernel-1.3.M03.jar +0 -0
- data/lib/neo4j/jars/core/neo4j-lucene-index-1.3.M03.jar +0 -0
- data/lib/neo4j/jars/ha/neo4j-com-1.3.M03.jar +0 -0
- data/lib/neo4j/jars/ha/neo4j-ha-1.3.M03.jar +0 -0
- data/lib/neo4j/jars/ha/neo4j-management-1.3.M03.jar +0 -0
- data/lib/neo4j/rails/relationships/mapper.rb +0 -103
- data/lib/neo4j/rails/relationships/relationship.rb +0 -30
@@ -0,0 +1,91 @@
|
|
1
|
+
module Neo4j
|
2
|
+
module Rails
|
3
|
+
module Relationships
|
4
|
+
|
5
|
+
class NodesDSL #:nodoc:
|
6
|
+
include Enumerable
|
7
|
+
|
8
|
+
def initialize(storage, dir)
|
9
|
+
@storage = storage
|
10
|
+
@dir = dir
|
11
|
+
end
|
12
|
+
|
13
|
+
def build(attrs)
|
14
|
+
self << (node = @storage.build(attrs))
|
15
|
+
node
|
16
|
+
end
|
17
|
+
|
18
|
+
def create(attrs)
|
19
|
+
self << (node = @storage.create(attrs))
|
20
|
+
node
|
21
|
+
end
|
22
|
+
|
23
|
+
def <<(other)
|
24
|
+
@storage.create_relationship_to(other, @dir)
|
25
|
+
self
|
26
|
+
end
|
27
|
+
|
28
|
+
def depth(d)
|
29
|
+
adapt_to_traverser.depth(d)
|
30
|
+
end
|
31
|
+
|
32
|
+
def adapt_to_traverser
|
33
|
+
Neo4j::Traversal::Traverser.new(@storage.node, @storage.rel_type, @dir)
|
34
|
+
end
|
35
|
+
|
36
|
+
def [](index)
|
37
|
+
i = 0
|
38
|
+
each{|x| return x if i == index; i += 1}
|
39
|
+
nil # out of index
|
40
|
+
end
|
41
|
+
|
42
|
+
def is_a?(type)
|
43
|
+
# ActionView requires this for nested attributes to work
|
44
|
+
return true if Array == type
|
45
|
+
super
|
46
|
+
end
|
47
|
+
|
48
|
+
def find(*args, &block)
|
49
|
+
return super(*args, &block) if block
|
50
|
+
node = args.first
|
51
|
+
enum = Enumerator.new(@storage, :each_rel, @dir)
|
52
|
+
if @dir == :incoming
|
53
|
+
enum.find{|r| r.start_node == node}
|
54
|
+
else
|
55
|
+
enum.find{|r| r.end_node == node}
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def destroy_all
|
60
|
+
each {|n| n.destroy}
|
61
|
+
end
|
62
|
+
|
63
|
+
def delete_all
|
64
|
+
each {|n| n.delete}
|
65
|
+
end
|
66
|
+
|
67
|
+
def size
|
68
|
+
@storage.size(@dir)
|
69
|
+
end
|
70
|
+
|
71
|
+
alias :length :size
|
72
|
+
|
73
|
+
def each(&block)
|
74
|
+
@storage.each_node(@dir, &block)
|
75
|
+
end
|
76
|
+
|
77
|
+
def delete(*nodes)
|
78
|
+
@storage.destroy_rels(@dir, *nodes)
|
79
|
+
end
|
80
|
+
|
81
|
+
def empty?
|
82
|
+
size == 0 # TODO, performance: there are probably faster way of doing this
|
83
|
+
end
|
84
|
+
|
85
|
+
def to_s
|
86
|
+
"Node dir: #{@dir}, #{@storage}"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -2,65 +2,72 @@ module Neo4j
|
|
2
2
|
module Rails
|
3
3
|
module Relationships
|
4
4
|
|
5
|
-
# TODO, reuse for incoming relationships ?
|
6
|
-
class OutgoingRelationship #:nodoc:
|
7
|
-
include Enumerable
|
8
5
|
|
9
|
-
|
10
|
-
|
11
|
-
|
6
|
+
def write_changed_relationships #:nodoc:
|
7
|
+
@relationships.each_value do |storage|
|
8
|
+
storage.persist
|
12
9
|
end
|
10
|
+
end
|
13
11
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
end
|
12
|
+
def clear_relationships #:nodoc:
|
13
|
+
@relationships = {}
|
14
|
+
end
|
18
15
|
|
19
|
-
def size
|
20
|
-
@mapper.dsl.all_relationships(@from_node).size
|
21
|
-
end
|
22
16
|
|
23
|
-
|
24
|
-
|
25
|
-
|
17
|
+
def _create_or_get_storage(rel_type) #:nodoc:
|
18
|
+
dsl = _decl_rels_for(rel_type.to_sym)
|
19
|
+
@relationships[rel_type.to_sym] ||= Storage.new(self, rel_type, dsl)
|
26
20
|
end
|
27
21
|
|
22
|
+
def _create_or_get_storage_for_decl_rels(decl_rels) #:nodoc:
|
23
|
+
@relationships[decl_rels.rel_type.to_sym] ||= Storage.new(self, decl_rels.rel_type, decl_rels)
|
24
|
+
end
|
28
25
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
26
|
+
|
27
|
+
# If the node is persisted and it does not have any unsaved relationship it returns a Neo4j::NodeTraverser.
|
28
|
+
# Otherwise it will return a NodesDSL which behaves like the Neo4j::NodeTraverser except that it does not
|
29
|
+
# allow to traverse both persisted and not persisted (not saved yet) relationship more then depth one.
|
30
|
+
#
|
31
|
+
# See, Neo4j::NodeRelationship#outgoing (when node is persisted) which returns a Neo4j::NodeTraverser
|
32
|
+
#
|
33
|
+
def outgoing(rel_type)
|
34
|
+
storage = _create_or_get_storage(rel_type)
|
35
|
+
NodesDSL.new(storage, :outgoing)
|
33
36
|
end
|
34
37
|
|
35
|
-
|
36
|
-
|
38
|
+
|
39
|
+
# Traverse or update an incoming relationship
|
40
|
+
# See #outgoing
|
41
|
+
# See, Neo4j::NodeRelationship#outgoing (when node is persisted) which returns a Neo4j::NodeTraverser
|
42
|
+
def incoming(rel_type)
|
43
|
+
storage = _create_or_get_storage(rel_type)
|
44
|
+
NodesDSL.new(storage, :incoming)
|
37
45
|
end
|
38
46
|
|
39
|
-
|
40
|
-
|
41
|
-
|
47
|
+
# See Neo4j::Rels#rels.
|
48
|
+
# Will also allow to access unsaved relationships - like the #outgoing and #incoming method.
|
49
|
+
#
|
50
|
+
def rels(*rel_types)
|
51
|
+
storage = _create_or_get_storage(rel_types.first)
|
52
|
+
RelsDSL.new(storage)
|
42
53
|
end
|
43
54
|
|
55
|
+
def add_outgoing_rel(rel_type, rel) #:nodoc:
|
56
|
+
_create_or_get_storage(rel_type).add_outgoing_rel(rel)
|
57
|
+
end
|
44
58
|
|
45
|
-
def
|
46
|
-
|
59
|
+
def add_incoming_rel(rel_type, rel) #:nodoc:
|
60
|
+
_create_or_get_storage(rel_type).add_incoming_rel(rel)
|
47
61
|
end
|
48
62
|
|
63
|
+
def rm_incoming_rel(rel_type, rel) #:nodoc:
|
64
|
+
_create_or_get_storage(rel_type).rm_incoming_rel(rel)
|
65
|
+
end
|
49
66
|
|
50
|
-
|
51
|
-
|
52
|
-
# If not persisted the traversal method like prune, expand, filter etc. will not be available
|
53
|
-
#
|
54
|
-
# See, Neo4j::NodeRelationship#outgoing (when node is persisted) which returns a Neo4j::NodeTraverser
|
55
|
-
#
|
56
|
-
def outgoing(rel_type)
|
57
|
-
if persisted?
|
58
|
-
super
|
59
|
-
else
|
60
|
-
dsl = _decl_rels_for(rel_type)
|
61
|
-
OutgoingRelationship.new(self, dsl)
|
62
|
-
end
|
67
|
+
def rm_outgoing_rel(rel_type, rel) #:nodoc:
|
68
|
+
_create_or_get_storage(rel_type).rm_outgoing_rel(rel)
|
63
69
|
end
|
70
|
+
|
64
71
|
end
|
65
72
|
end
|
66
73
|
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module Neo4j
|
2
|
+
module Rails
|
3
|
+
module Relationships
|
4
|
+
class RelsDSL
|
5
|
+
include Enumerable
|
6
|
+
|
7
|
+
def initialize(storage, dir=:both)
|
8
|
+
@storage = storage
|
9
|
+
@dir = dir
|
10
|
+
end
|
11
|
+
|
12
|
+
|
13
|
+
def build(attrs)
|
14
|
+
node = @storage.build(attrs)
|
15
|
+
@storage.create_relationship_to(node, @dir)
|
16
|
+
end
|
17
|
+
|
18
|
+
def create(attrs)
|
19
|
+
node = @storage.create(attrs)
|
20
|
+
@storage.create_relationship_to(node, @dir)
|
21
|
+
end
|
22
|
+
|
23
|
+
def outgoing
|
24
|
+
@dir = :outgoing
|
25
|
+
self
|
26
|
+
end
|
27
|
+
|
28
|
+
def incoming
|
29
|
+
@dir = :incoming
|
30
|
+
self
|
31
|
+
end
|
32
|
+
|
33
|
+
def each(&block)
|
34
|
+
@storage.each_rel(@dir, &block)
|
35
|
+
end
|
36
|
+
|
37
|
+
def size
|
38
|
+
@storage.size(@dir)
|
39
|
+
end
|
40
|
+
|
41
|
+
def empty?
|
42
|
+
size == 0
|
43
|
+
end
|
44
|
+
|
45
|
+
def destroy_all
|
46
|
+
each {|n| n.destroy}
|
47
|
+
end
|
48
|
+
|
49
|
+
def delete_all
|
50
|
+
each {|n| n.delete}
|
51
|
+
end
|
52
|
+
|
53
|
+
def find(*args, &block)
|
54
|
+
return super(*args, &block) if block
|
55
|
+
node = args.first
|
56
|
+
if @dir == :incoming
|
57
|
+
find{|r| r.start_node == node}
|
58
|
+
else
|
59
|
+
find{|r| r.end_node == node}
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def [](index)
|
64
|
+
i = 0
|
65
|
+
each{|x| return x if i == index; i += 1}
|
66
|
+
nil # out of index
|
67
|
+
end
|
68
|
+
|
69
|
+
def is_a?(type)
|
70
|
+
# ActionView requires this for nested attributes to work
|
71
|
+
return true if Array == type
|
72
|
+
super
|
73
|
+
end
|
74
|
+
|
75
|
+
def to_s
|
76
|
+
"Rels dir: #{@dir}, #{@storage}"
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,161 @@
|
|
1
|
+
module Neo4j
|
2
|
+
module Rails
|
3
|
+
module Relationships
|
4
|
+
|
5
|
+
# Holds the relationships in memory but also allows read access to persisted relationships
|
6
|
+
class Storage #:nodoc:
|
7
|
+
include Neo4j::ToJava
|
8
|
+
attr_reader :dsl, :node, :rel_type
|
9
|
+
|
10
|
+
def initialize(node, rel_type, dsl)
|
11
|
+
@rel_type = rel_type.to_sym
|
12
|
+
@node = node
|
13
|
+
@rel_class = (dsl && dsl.relationship_class) || Neo4j::Rails::Relationship
|
14
|
+
@target_class = (dsl && dsl.target_class) || Neo4j::Rails::Model
|
15
|
+
@outgoing_rels = []
|
16
|
+
@incoming_rels = []
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_s #:nodoc:
|
20
|
+
"Storage #{object_id} node: #{@node.id} rel_type: #{@rel_type} outgoing #{@outgoing_rels.size} incoming #{@incoming_rels.size}"
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
def size(dir)
|
25
|
+
counter = 0
|
26
|
+
# count persisted relationship
|
27
|
+
@node._java_node && @node._java_node.getRelationships(java_rel_type, dir_to_java(dir)).each { |*| counter += 1 }
|
28
|
+
# count relationship which has not yet been persisted
|
29
|
+
counter += relationships(dir).size
|
30
|
+
counter
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
def build(attrs)
|
35
|
+
@target_class.new(attrs)
|
36
|
+
end
|
37
|
+
|
38
|
+
def create(attrs)
|
39
|
+
@target_class.create(attrs)
|
40
|
+
end
|
41
|
+
|
42
|
+
def relationships(dir)
|
43
|
+
case dir
|
44
|
+
when :outgoing
|
45
|
+
@outgoing_rels
|
46
|
+
when :incoming
|
47
|
+
@incoming_rels
|
48
|
+
when :both
|
49
|
+
@incoming_rels + @outgoing_rels
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def java_rel_type
|
54
|
+
type_to_java(rel_type)
|
55
|
+
end
|
56
|
+
|
57
|
+
def each_rel(dir, &block) #:nodoc:
|
58
|
+
relationships(dir).each { |rel| block.call rel }
|
59
|
+
|
60
|
+
if @node.persisted?
|
61
|
+
node._java_node.getRelationships(java_rel_type, dir_to_java(dir)).each do |rel|
|
62
|
+
block.call rel.wrapper
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def each_node(dir, &block)
|
68
|
+
relationships(dir).each do |rel|
|
69
|
+
if rel.start_node == @node
|
70
|
+
block.call rel.end_node
|
71
|
+
else
|
72
|
+
block.call rel.start_node
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
if @node.persisted?
|
77
|
+
@node._java_node.getRelationships(java_rel_type, dir_to_java(dir)).each do |rel|
|
78
|
+
block.call rel.getOtherNode(@node._java_node).wrapper
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def single_relationship(dir)
|
84
|
+
rel = relationships(dir).first
|
85
|
+
if rel.nil? && @node.persisted?
|
86
|
+
java_rel = @node._java_node.getSingleRelationship(java_rel_type, dir_to_java(dir))
|
87
|
+
java_rel && java_rel.wrapper
|
88
|
+
else
|
89
|
+
rel
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def all_relationships(dir)
|
94
|
+
Enumerator.new(self, :each_rel, dir)
|
95
|
+
end
|
96
|
+
|
97
|
+
def single_node(dir)
|
98
|
+
rel = single_relationship(dir)
|
99
|
+
return nil if rel.nil?
|
100
|
+
other = rel.other_node(@node)
|
101
|
+
other && other.wrapper
|
102
|
+
end
|
103
|
+
|
104
|
+
def destroy_rels(dir, *nodes)
|
105
|
+
all_relationships(dir).each do |rel|
|
106
|
+
node = dir == :outgoing ? rel.end_node : rel.start_node
|
107
|
+
dir == :incoming ? rm_incoming_rel(rel) : rm_outgoing_rel(rel)
|
108
|
+
rel.destroy if nodes.include?(node)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def create_relationship_to(to, dir)
|
113
|
+
if dir == :outgoing
|
114
|
+
@rel_class.new(@rel_type, @node, to, self)
|
115
|
+
else
|
116
|
+
@rel_class.new(@rel_type, to, @node, self)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def add_incoming_rel(rel)
|
121
|
+
@incoming_rels << rel
|
122
|
+
end
|
123
|
+
|
124
|
+
def add_outgoing_rel(rel)
|
125
|
+
@outgoing_rels << rel
|
126
|
+
end
|
127
|
+
|
128
|
+
def rm_incoming_rel(rel)
|
129
|
+
@incoming_rels.delete(rel)
|
130
|
+
end
|
131
|
+
|
132
|
+
def rm_outgoing_rel(rel)
|
133
|
+
@outgoing_rels.delete(rel)
|
134
|
+
end
|
135
|
+
|
136
|
+
def persist
|
137
|
+
out_rels = @outgoing_rels.clone
|
138
|
+
in_rels = @incoming_rels.clone
|
139
|
+
|
140
|
+
@outgoing_rels.clear
|
141
|
+
@incoming_rels.clear
|
142
|
+
|
143
|
+
out_rels.each do |rel|
|
144
|
+
rel.end_node.rm_incoming_rel(@rel_type.to_sym, rel)
|
145
|
+
success = rel.persisted? || rel.save
|
146
|
+
# don't think this can happen - just in case, TODO
|
147
|
+
raise "Can't save outgoing #{rel}, validation errors ? #{rel.errors.inspect}" unless success
|
148
|
+
end
|
149
|
+
|
150
|
+
in_rels.each do |rel|
|
151
|
+
rel.start_node.rm_outgoing_rel(@rel_type.to_sym, rel)
|
152
|
+
success = rel.persisted? || rel.save
|
153
|
+
# don't think this can happen - just in case, TODO
|
154
|
+
raise "Can't save incoming #{rel}, validation errors ? #{rel.errors.inspect}" unless success
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
@@ -5,7 +5,7 @@ module Neo4j
|
|
5
5
|
|
6
6
|
included do
|
7
7
|
include ActiveModel::Serializers::Xml
|
8
|
-
|
8
|
+
include ActiveModel::Serializers::JSON
|
9
9
|
# Patch for ActiveModel's XML serializer. There is a bug in the original where
|
10
10
|
# raw_value is used in the initializer and so demands always that the object being
|
11
11
|
# serialized is sent the attribute's name as a method call. This causes a problem
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Neo4j
|
2
|
+
module Rails
|
3
|
+
module Validations
|
4
|
+
class AssociatedValidator < ActiveModel::EachValidator
|
5
|
+
def validate_each(record, attribute, value)
|
6
|
+
return if (value.is_a?(Enumerable) ? value : [value]).collect { |r| r.nil? || r.valid? }.all?
|
7
|
+
record.errors.add(attribute, :invalid, options.merge(:value => value))
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
# Validates whether the associated object or objects are all valid themselves. Works with any kind of association.
|
13
|
+
#
|
14
|
+
# class Book < Neo4j::Rails::Model
|
15
|
+
# has_n :pages
|
16
|
+
# belongs_to :library
|
17
|
+
#
|
18
|
+
# validates_associated :pages, :library
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# Warning: If, after the above definition, you then wrote:
|
22
|
+
#
|
23
|
+
# class Page < Neo4j::Rails::Model
|
24
|
+
# has_n(:book).from(:pages)
|
25
|
+
#
|
26
|
+
# validates_associated :book
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# this would specify a circular dependency and cause infinite recursion.
|
30
|
+
#
|
31
|
+
# NOTE: This validation will not fail if the association hasn't been assigned. If you want to
|
32
|
+
# ensure that the association is both present and guaranteed to be valid, you also need to
|
33
|
+
# use +validates_presence_of+.
|
34
|
+
#
|
35
|
+
# Configuration options:
|
36
|
+
# * <tt>:message</tt> - A custom error message (default is: "is invalid")
|
37
|
+
# * <tt>:on</tt> - Specifies when this validation is active (default is <tt>:save</tt>, other options <tt>:create</tt>, <tt>:update</tt>).
|
38
|
+
# * <tt>:if</tt> - Specifies a method, proc or string to call to determine if the validation should
|
39
|
+
# occur (e.g. <tt>:if => :allow_validation</tt>, or <tt>:if => Proc.new { |user| user.signup_step > 2 }</tt>). The
|
40
|
+
# method, proc or string should return or evaluate to a true or false value.
|
41
|
+
# * <tt>:unless</tt> - Specifies a method, proc or string to call to determine if the validation should
|
42
|
+
# not occur (e.g. <tt>:unless => :skip_validation</tt>, or <tt>:unless => Proc.new { |user| user.signup_step <= 2 }</tt>). The
|
43
|
+
# method, proc or string should return or evaluate to a true or false value.
|
44
|
+
def validates_associated(*attr_names)
|
45
|
+
validates_with AssociatedValidator, _merge_attributes(attr_names)
|
46
|
+
rel_attr_names = attr_names.collect{|a| a.is_a?(Symbol) && _decl_rels[a].has_one? ? "#{a}_rel" : a}
|
47
|
+
rel_attr_names = rel_attr_names.collect{|a| a.is_a?(Symbol) && _decl_rels[a].has_n? ? "#{a}_rels" : a}
|
48
|
+
validates_with AssociatedValidator, _merge_attributes(rel_attr_names)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -15,9 +15,8 @@ module Neo4j
|
|
15
15
|
|
16
16
|
def valid?(context = nil)
|
17
17
|
context ||= (new_record? ? :create : :update)
|
18
|
-
|
19
|
-
|
20
|
-
errors.empty? && output && output_rels
|
18
|
+
super(context)
|
19
|
+
errors.empty?
|
21
20
|
end
|
22
21
|
|
23
22
|
private
|
data/lib/neo4j/relationship.rb
CHANGED
@@ -140,9 +140,9 @@ module Neo4j
|
|
140
140
|
#
|
141
141
|
# Neo4j::Relationship.new :friend, node1, node2, :since => '2001-01-02', :status => 'okey'
|
142
142
|
#
|
143
|
-
def new(type,
|
143
|
+
def new(type, start_node, end_node, props=nil)
|
144
144
|
java_type = type_to_java(type)
|
145
|
-
rel =
|
145
|
+
rel = start_node._java_node.create_relationship_to(end_node._java_node, java_type)
|
146
146
|
props.each_pair {|k,v| rel[k] = v} if props
|
147
147
|
rel
|
148
148
|
end
|
@@ -164,7 +164,7 @@ module Neo4j
|
|
164
164
|
|
165
165
|
# Same as load but does not return the node as a wrapped Ruby object.
|
166
166
|
#
|
167
|
-
def _load(rel_id, db)
|
167
|
+
def _load(rel_id, db = Neo4j.started_db)
|
168
168
|
rel = db.graph.get_relationship_by_id(rel_id.to_i)
|
169
169
|
rel.hasProperty('_classname') # since we want a IllegalStateException which is otherwise not triggered
|
170
170
|
rel
|
@@ -59,6 +59,10 @@ module Neo4j
|
|
59
59
|
@_java_rel
|
60
60
|
end
|
61
61
|
|
62
|
+
def _java_entity
|
63
|
+
@_java_rel
|
64
|
+
end
|
65
|
+
|
62
66
|
# Returns the end node of this relationship
|
63
67
|
def end_node
|
64
68
|
id = getEndNode.getId
|
@@ -127,7 +131,7 @@ module Neo4j
|
|
127
131
|
c.extend Neo4j::Index::ClassMethods
|
128
132
|
|
129
133
|
def c.inherited(subclass)
|
130
|
-
subclass.rel_indexer
|
134
|
+
subclass.rel_indexer self
|
131
135
|
super
|
132
136
|
end
|
133
137
|
|
data/lib/neo4j/rels/traverser.rb
CHANGED
@@ -12,23 +12,23 @@ module Neo4j
|
|
12
12
|
include Enumerable
|
13
13
|
include ToJava
|
14
14
|
|
15
|
-
def initialize(node, types,
|
15
|
+
def initialize(node, types, dir)
|
16
16
|
@node = node
|
17
17
|
if types.size > 1
|
18
18
|
@types = types.inject([]) { |result, type| result << type_to_java(type) }.to_java(:'org.neo4j.graphdb.RelationshipType')
|
19
19
|
elsif types.size == 1
|
20
20
|
@type = type_to_java(types[0])
|
21
21
|
end
|
22
|
-
@
|
22
|
+
@dir = dir
|
23
23
|
end
|
24
24
|
|
25
25
|
def to_s
|
26
26
|
if @type
|
27
|
-
"#{self.class} [type: #{@type} dir:#{@
|
27
|
+
"#{self.class} [type: #{@type} dir:#{@dir}]"
|
28
28
|
elsif @types
|
29
|
-
"#{self.class} [types: #{@types.join(',')} dir:#{@
|
29
|
+
"#{self.class} [types: #{@types.join(',')} dir:#{@dir}]"
|
30
30
|
else
|
31
|
-
"#{self.class} [types: ANY dir:#{@
|
31
|
+
"#{self.class} [types: ANY dir:#{@dir}]"
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
@@ -48,18 +48,18 @@ module Neo4j
|
|
48
48
|
if @types
|
49
49
|
@node.get_relationships(@types).iterator
|
50
50
|
elsif @type
|
51
|
-
@node.get_relationships(@type, dir_to_java(@
|
51
|
+
@node.get_relationships(@type, dir_to_java(@dir))
|
52
52
|
else
|
53
|
-
@node.get_relationships(dir_to_java(@
|
53
|
+
@node.get_relationships(dir_to_java(@dir))
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
57
57
|
def match_to_other?(rel)
|
58
58
|
if @to_other.nil?
|
59
59
|
true
|
60
|
-
elsif @
|
60
|
+
elsif @dir == :outgoing
|
61
61
|
rel._end_node == @to_other
|
62
|
-
elsif @
|
62
|
+
elsif @dir == :incoming
|
63
63
|
rel._start_node == @to_other
|
64
64
|
else
|
65
65
|
rel._start_node == @to_other || rel._end_node == @to_other
|
@@ -80,19 +80,19 @@ module Neo4j
|
|
80
80
|
end
|
81
81
|
|
82
82
|
def both
|
83
|
-
@
|
83
|
+
@dir = :both
|
84
84
|
self
|
85
85
|
end
|
86
86
|
|
87
87
|
def incoming
|
88
88
|
raise "Not allowed calling incoming when finding several relationships types" if @types
|
89
|
-
@
|
89
|
+
@dir = :incoming
|
90
90
|
self
|
91
91
|
end
|
92
92
|
|
93
93
|
def outgoing
|
94
94
|
raise "Not allowed calling outgoing when finding several relationships types" if @types
|
95
|
-
@
|
95
|
+
@dir = :outgoing
|
96
96
|
self
|
97
97
|
end
|
98
98
|
|
data/lib/neo4j/rule/rule_node.rb
CHANGED
@@ -7,6 +7,7 @@ module Neo4j
|
|
7
7
|
# The RuleNode can also be used to hold properties for functions, like sum and count.
|
8
8
|
#
|
9
9
|
class RuleNode
|
10
|
+
include ToJava
|
10
11
|
attr_reader :rules
|
11
12
|
|
12
13
|
def initialize(clazz)
|
@@ -26,7 +27,7 @@ module Neo4j
|
|
26
27
|
def create_node
|
27
28
|
Neo4j::Transaction.run do
|
28
29
|
node = Neo4j::Node.new
|
29
|
-
Neo4j.ref_node.
|
30
|
+
Neo4j.ref_node.create_relationship_to(node, type_to_java(@clazz))
|
30
31
|
node
|
31
32
|
end
|
32
33
|
end
|
data/lib/neo4j/to_java.rb
CHANGED