neo4j 1.0.0-java → 1.1.0.beta.1-java
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.
- 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