neo4j 1.2.6-java → 2.0.0.alpha.3-java
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +30 -0
- data/CONTRIBUTORS +1 -0
- data/Gemfile +16 -4
- data/README.rdoc +25 -3
- data/bin/neo4j-jars +15 -8
- data/bin/neo4j-shell +0 -1
- data/bin/neo4j-upgrade +72 -0
- data/config/neo4j/config.yml +5 -4
- data/lib/neo4j/algo/algo.rb +0 -1
- data/lib/neo4j/batch/inserter.rb +5 -0
- data/lib/neo4j/database.rb +18 -12
- data/lib/neo4j/event_handler.rb +76 -9
- data/lib/neo4j/has_list/class_methods.rb +1 -1
- data/lib/neo4j/has_list/mapping.rb +13 -33
- data/lib/neo4j/has_n/decl_relationship_dsl.rb +17 -13
- data/lib/neo4j/has_n/mapping.rb +6 -23
- data/lib/neo4j/identity_map.rb +0 -3
- data/lib/neo4j/index/class_methods.rb +9 -3
- data/lib/neo4j/index/index.rb +2 -1
- data/lib/neo4j/index/indexer.rb +3 -2
- data/lib/neo4j/index/indexer_registry.rb +1 -1
- data/lib/neo4j/index/lucene_query.rb +52 -33
- data/lib/neo4j/neo4j.rb +19 -0
- data/lib/neo4j/node.rb +42 -36
- data/lib/neo4j/node_mixin/node_mixin.rb +9 -5
- data/lib/neo4j/paginated.rb +23 -0
- data/lib/neo4j/rails/accept_id.rb +66 -0
- data/lib/neo4j/rails/attributes.rb +14 -9
- data/lib/neo4j/rails/compositions.rb +9 -1
- data/lib/neo4j/rails/finders.rb +5 -1
- data/lib/neo4j/rails/mapping/property.rb +41 -28
- data/lib/neo4j/rails/model.rb +2 -0
- data/lib/neo4j/rails/observer.rb +61 -2
- data/lib/neo4j/rails/persistence.rb +57 -57
- data/lib/neo4j/rails/rails.rb +1 -0
- data/lib/neo4j/rails/railtie.rb +4 -1
- data/lib/neo4j/rails/rel_persistence.rb +11 -12
- data/lib/neo4j/rails/relationship.rb +9 -4
- data/lib/neo4j/rails/relationships/node_dsl.rb +15 -5
- data/lib/neo4j/rails/relationships/relationships.rb +42 -2
- data/lib/neo4j/rails/relationships/rels_dsl.rb +60 -3
- data/lib/neo4j/rails/relationships/storage.rb +43 -5
- data/lib/neo4j/rails/validations/uniqueness.rb +1 -0
- data/lib/neo4j/rails/versioning/versioning.rb +64 -9
- data/lib/neo4j/relationship.rb +79 -73
- data/lib/neo4j/rule/event_listener.rb +7 -1
- data/lib/neo4j/rule/functions/count.rb +6 -0
- data/lib/neo4j/rule/rule.rb +20 -5
- data/lib/neo4j/rule/rule_node.rb +33 -20
- data/lib/neo4j/to_java.rb +5 -0
- data/lib/neo4j/traversal/traverser.rb +38 -1
- data/lib/neo4j/type_converters/type_converters.rb +56 -5
- data/lib/neo4j/version.rb +1 -1
- data/lib/neo4j.rb +3 -49
- data/neo4j.gemspec +2 -2
- metadata +191 -216
- data/bin/neo4j-shell~ +0 -108
- data/lib/Gemfile~ +0 -3
- data/lib/config2.yml~ +0 -86
- data/lib/neo4j/jars/core/geronimo-jta_1.1_spec-1.1.1.jar +0 -0
- data/lib/neo4j/jars/core/lucene-core-3.1.0.jar +0 -0
- data/lib/neo4j/jars/core/neo4j-backup-1.4.1.jar +0 -0
- data/lib/neo4j/jars/core/neo4j-graph-algo-1.4.1.jar +0 -0
- data/lib/neo4j/jars/core/neo4j-index-1.3-1.3.M01.jar +0 -0
- data/lib/neo4j/jars/core/neo4j-kernel-1.4.1.jar +0 -0
- data/lib/neo4j/jars/core/neo4j-lucene-index-1.4.1.jar +0 -0
- data/lib/neo4j/jars/ha/log4j-1.2.16.jar +0 -0
- data/lib/neo4j/jars/ha/neo4j-com-1.4.1.jar +0 -0
- data/lib/neo4j/jars/ha/neo4j-ha-1.4.1.jar +0 -0
- data/lib/neo4j/jars/ha/neo4j-jmx-1.4.1.jar +0 -0
- data/lib/neo4j/jars/ha/neo4j-management-1.4.1.jar +0 -0
- data/lib/neo4j/jars/ha/neo4j-shell-1.4.1.jar +0 -0
- data/lib/neo4j/jars/ha/netty-3.2.1.Final.jar +0 -0
- data/lib/neo4j/jars/ha/org.apache.servicemix.bundles.jline-0.9.94_1.jar +0 -0
- data/lib/neo4j/jars/ha/zookeeper-3.3.2.jar +0 -0
- data/lib/neo4j/paginate.rb +0 -25
- data/lib/perf.rb~ +0 -36
- data/lib/test.rb~ +0 -2
@@ -206,6 +206,14 @@ module Neo4j
|
|
206
206
|
# :constructor => Proc.new { |ip| IPAddr.new(ip, Socket::AF_INET) },
|
207
207
|
# :converter => Proc.new { |ip| ip.is_a?(Integer) ? IPAddr.new(ip, Socket::AF_INET) : IPAddr.new(ip.to_s) }
|
208
208
|
#
|
209
|
+
def is_composed_property?(property)
|
210
|
+
composed_properties.contains(property)
|
211
|
+
end
|
212
|
+
|
213
|
+
def composed_properties
|
214
|
+
@composed_properties ||= java.util.HashSet.new
|
215
|
+
end
|
216
|
+
|
209
217
|
def composed_of(part_id, options = {})
|
210
218
|
options.assert_valid_keys(:class_name, :mapping, :allow_nil, :constructor, :converter)
|
211
219
|
|
@@ -216,7 +224,7 @@ module Neo4j
|
|
216
224
|
allow_nil = options[:allow_nil] || false
|
217
225
|
constructor = options[:constructor] || :new
|
218
226
|
converter = options[:converter]
|
219
|
-
|
227
|
+
composed_properties.add(name.to_sym)
|
220
228
|
reader_method(name, class_name, mapping, allow_nil, constructor)
|
221
229
|
writer_method(name, class_name, mapping, allow_nil, converter)
|
222
230
|
end
|
data/lib/neo4j/rails/finders.rb
CHANGED
@@ -76,7 +76,7 @@ module Neo4j
|
|
76
76
|
when "0", 0, nil
|
77
77
|
nil
|
78
78
|
else
|
79
|
-
if
|
79
|
+
if convertable_to_id?(args.first)
|
80
80
|
find_with_ids(*args)
|
81
81
|
else
|
82
82
|
first(*args)
|
@@ -167,6 +167,10 @@ module Neo4j
|
|
167
167
|
condition.is_a?(Hash) && condition[:id]
|
168
168
|
end
|
169
169
|
|
170
|
+
def convertable_to_id?(value)
|
171
|
+
return false unless value
|
172
|
+
value.is_a?(Integer) || (value.is_a?(String) && value =~ /^[+-]?\d+$/)
|
173
|
+
end
|
170
174
|
|
171
175
|
def conditions_in?(*args)
|
172
176
|
return false if args.empty?
|
@@ -55,8 +55,7 @@ module Neo4j
|
|
55
55
|
def #{rel_type}=(other)
|
56
56
|
dsl = _decl_rels_for(:'#{rel_type}')
|
57
57
|
storage = _create_or_get_storage_for_decl_rels(dsl)
|
58
|
-
|
59
|
-
rel && rel.destroy
|
58
|
+
storage.destroy_single_relationship(dsl.dir)
|
60
59
|
storage.create_relationship_to(other, dsl.dir)
|
61
60
|
end
|
62
61
|
RUBY
|
@@ -76,9 +75,21 @@ module Neo4j
|
|
76
75
|
end
|
77
76
|
|
78
77
|
unless method_defined?("#{rel_type}=".to_sym)
|
78
|
+
|
79
|
+
# TODO: This is a temporary fix for allowing running neo4j with Formtastic, issue 109
|
80
|
+
# A better solution might be to implement accept_ids for has_n relationship and
|
81
|
+
# make sure (somehow) that Formtastic uses the _ids methods.
|
82
|
+
|
79
83
|
class_eval <<-RUBY, __FILE__, __LINE__
|
80
84
|
def #{rel_type}=(nodes)
|
81
|
-
|
85
|
+
if nodes.is_a?(Array) && nodes.first.is_a?(String)
|
86
|
+
if nodes.first.blank?
|
87
|
+
self.#{rel_type}_rels.destroy_all
|
88
|
+
nodes.shift
|
89
|
+
end
|
90
|
+
else
|
91
|
+
self.#{rel_type}_rels.destroy_all
|
92
|
+
end
|
82
93
|
association = self.#{rel_type}
|
83
94
|
nodes.each { |node| association << node }
|
84
95
|
end
|
@@ -106,10 +117,10 @@ module Neo4j
|
|
106
117
|
|
107
118
|
# Handles options for the property
|
108
119
|
#
|
109
|
-
# Set the property type
|
110
|
-
# Set a default
|
111
|
-
# Property must be there
|
112
|
-
# Property has a length limit
|
120
|
+
# Set the property type :type => Time
|
121
|
+
# Set a default :default => "default"
|
122
|
+
# Property must be there :null => false
|
123
|
+
# Property has a length limit :limit => 128
|
113
124
|
def property(*args)
|
114
125
|
options = args.extract_options!
|
115
126
|
args.each do |property_sym|
|
@@ -132,39 +143,41 @@ module Neo4j
|
|
132
143
|
validates(property, :non_nil => true, :on => :create)
|
133
144
|
validates(property, :non_nil => true, :on => :update)
|
134
145
|
end
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
146
|
+
validates(property, :length => { :maximum => options[:limit] }) if options[:limit]
|
147
|
+
end
|
148
|
+
|
149
|
+
def define_property_methods_for(property, options)
|
150
|
+
unless method_defined?(property)
|
151
|
+
class_eval <<-RUBY, __FILE__, __LINE__
|
152
|
+
def #{property}
|
153
|
+
send(:[], "#{property}")
|
154
|
+
end
|
144
155
|
RUBY
|
145
156
|
end
|
146
157
|
|
147
158
|
unless method_defined?("#{property}=".to_sym)
|
148
159
|
class_eval <<-RUBY, __FILE__, __LINE__
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
160
|
+
def #{property}=(value)
|
161
|
+
send(:[]=, "#{property}", value)
|
162
|
+
end
|
163
|
+
RUBY
|
164
|
+
end
|
165
|
+
end
|
155
166
|
|
156
167
|
def define_property_before_type_cast_methods_for(property, options)
|
157
168
|
property_before_type_cast = "#{property}_before_type_cast"
|
158
169
|
class_eval <<-RUBY, __FILE__, __LINE__
|
159
|
-
|
170
|
+
def #{property_before_type_cast}=(value)
|
171
|
+
@properties_before_type_cast[:#{property}]=value
|
172
|
+
end
|
160
173
|
|
161
174
|
def #{property_before_type_cast}
|
162
|
-
|
175
|
+
@properties_before_type_cast.has_key?(:#{property}) ? @properties_before_type_cast[:#{property}] : self.#{property}
|
163
176
|
end
|
164
177
|
RUBY
|
165
178
|
end
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
170
183
|
end
|
data/lib/neo4j/rails/model.rb
CHANGED
@@ -48,6 +48,7 @@ module Neo4j
|
|
48
48
|
|
49
49
|
# Initialize a Node with a set of properties (or empty if nothing is passed)
|
50
50
|
def initialize(attributes = {})
|
51
|
+
@properties_before_type_cast=java.util.HashMap.new
|
51
52
|
reset_attributes
|
52
53
|
clear_relationships
|
53
54
|
self.attributes = attributes if attributes.is_a?(Hash)
|
@@ -269,6 +270,7 @@ module Neo4j
|
|
269
270
|
include Finders # ActiveRecord style find
|
270
271
|
include Relationships # for none persisted relationships
|
271
272
|
include Compositions
|
273
|
+
include AcceptId
|
272
274
|
end
|
273
275
|
end
|
274
276
|
end
|
data/lib/neo4j/rails/observer.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'active_support/core_ext/class/attribute_accessors'
|
2
|
+
|
1
3
|
module Neo4j
|
2
4
|
module Rails
|
3
5
|
# Observer classes respond to life cycle callbacks to implement trigger-like
|
@@ -86,11 +88,26 @@ module Neo4j
|
|
86
88
|
# In order to activate an observer, list it in the +config.neo4j.observers+
|
87
89
|
# configuration setting in your +config/application.rb+ file.
|
88
90
|
#
|
89
|
-
# config.neo4j.observers = :comment_observer, :signup_observer
|
91
|
+
# config.neo4j.observers = [:comment_observer, :signup_observer]
|
90
92
|
#
|
91
93
|
# Observers will not be invoked unless you define them in your
|
92
94
|
# application configuration.
|
93
95
|
#
|
96
|
+
# During testing you may want (and probably should) to disable all the observers.
|
97
|
+
# Most of the time you don't want any kind of emails to be sent when creating objects.
|
98
|
+
# This should improve the speed of your tests and isolate the models and observer logic.
|
99
|
+
#
|
100
|
+
# For example, the following will disable the observers in RSpec:
|
101
|
+
#
|
102
|
+
# config.before(:each) { Neo4j::Rails::Observer.disable_observers }
|
103
|
+
#
|
104
|
+
# But if you do want to run a particular observer(s) as part of the test,
|
105
|
+
# you can temporarily enable it:
|
106
|
+
#
|
107
|
+
# Neo4j::Rails::Observer.with_observers(:user_recorder, :account_observer) do
|
108
|
+
# # Any code here will work with observers enabled
|
109
|
+
# end
|
110
|
+
#
|
94
111
|
# == Loading
|
95
112
|
#
|
96
113
|
# Observers register themselves with the model class that they observe,
|
@@ -113,6 +130,48 @@ module Neo4j
|
|
113
130
|
super and observed_descendants.each { |klass| add_observer!(klass) }
|
114
131
|
end
|
115
132
|
|
133
|
+
cattr_accessor :default_observers_enabled, :observers_enabled
|
134
|
+
|
135
|
+
# TODO: Add docs
|
136
|
+
class << self
|
137
|
+
# Enables all observers (default behavior)
|
138
|
+
def enable_observers
|
139
|
+
self.default_observers_enabled = true
|
140
|
+
end
|
141
|
+
|
142
|
+
# Disables all observers
|
143
|
+
def disable_observers
|
144
|
+
self.default_observers_enabled = false
|
145
|
+
end
|
146
|
+
|
147
|
+
# Run a block with a specific set of observers enabled
|
148
|
+
def with_observers(*observer_syms)
|
149
|
+
self.observers_enabled = Array(observer_syms).map do |o|
|
150
|
+
o.respond_to?(:instance) ? o.instance : o.to_s.classify.constantize.instance
|
151
|
+
end
|
152
|
+
yield
|
153
|
+
ensure
|
154
|
+
self.observers_enabled = []
|
155
|
+
end
|
156
|
+
|
157
|
+
# Determines whether an observer is enabled. Either:
|
158
|
+
# - All observers are enabled OR
|
159
|
+
# - The observer is in the whitelist
|
160
|
+
def observer_enabled?(observer)
|
161
|
+
default_observers_enabled or self.observers_enabled.include?(observer)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
|
166
|
+
# Determines whether this observer should be run
|
167
|
+
def observer_enabled?
|
168
|
+
self.class.observer_enabled?(self)
|
169
|
+
end
|
170
|
+
|
171
|
+
# By default, enable all observers
|
172
|
+
enable_observers
|
173
|
+
self.observers_enabled = []
|
174
|
+
|
116
175
|
protected
|
117
176
|
|
118
177
|
# Get all the child observers.
|
@@ -149,7 +208,7 @@ module Neo4j
|
|
149
208
|
callback_meth = :"_notify_#{observer_name}_for_#{callback}"
|
150
209
|
unless klass.respond_to?(callback_meth)
|
151
210
|
klass.send(:define_method, callback_meth) do |&block|
|
152
|
-
observer.send(callback, self, &block)
|
211
|
+
observer.send(callback, self, &block) if observer.observer_enabled?
|
153
212
|
end
|
154
213
|
klass.send(callback, callback_meth)
|
155
214
|
end
|
@@ -1,62 +1,62 @@
|
|
1
1
|
module Neo4j
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
2
|
+
module Rails
|
3
|
+
module Persistence
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
extend TxMethods
|
8
|
+
tx_methods :destroy, :create, :update, :update_nested_attributes, :delete, :update_attributes, :update_attributes!
|
9
|
+
end
|
10
|
+
|
11
|
+
# Persist the object to the database. Validations and Callbacks are included
|
12
|
+
# by default but validation can be disabled by passing :validate => false
|
13
|
+
# to #save.
|
14
14
|
def save(*)
|
15
|
-
|
15
|
+
create_or_update
|
16
16
|
end
|
17
17
|
|
18
18
|
# Persist the object to the database. Validations and Callbacks are included
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
# by default but validation can be disabled by passing :validate => false
|
20
|
+
# to #save!.
|
21
|
+
#
|
22
|
+
# Raises a RecordInvalidError if there is a problem during save.
|
23
23
|
def save!(*args)
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
24
|
+
unless save(*args)
|
25
|
+
raise RecordInvalidError.new(self)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Updates a single attribute and saves the record.
|
30
|
+
# This is especially useful for boolean flags on existing records. Also note that
|
31
|
+
#
|
32
|
+
# * Validation is skipped.
|
33
|
+
# * Callbacks are invoked.
|
34
|
+
# * Updates all the attributes that are dirty in this object.
|
35
|
+
#
|
36
|
+
def update_attribute(name, value)
|
37
|
+
respond_to?("#{name}=") ? send("#{name}=", value) : self[name] = value
|
38
|
+
save(:validate => false)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Removes the node from Neo4j and freezes the object.
|
42
|
+
def destroy
|
43
|
+
delete
|
44
|
+
freeze
|
45
|
+
end
|
46
|
+
|
47
|
+
# Same as #destroy but doesn't run destroy callbacks and doesn't freeze
|
48
|
+
# the object
|
49
|
+
def delete
|
50
|
+
del unless new_record?
|
51
|
+
set_deleted_properties
|
52
|
+
end
|
53
|
+
|
54
|
+
# Returns true if the object was destroyed.
|
55
|
+
def destroyed?()
|
56
56
|
@_deleted || Neo4j::Node._load(id).nil?
|
57
57
|
end
|
58
58
|
|
59
|
-
|
59
|
+
# Updates this resource with all the attributes from the passed-in Hash and requests that the record be saved.
|
60
60
|
# If saving fails because the resource is invalid then false will be returned.
|
61
61
|
def update_attributes(attributes)
|
62
62
|
self.attributes = attributes
|
@@ -95,9 +95,9 @@ module Neo4j
|
|
95
95
|
alias :new? :new_record?
|
96
96
|
|
97
97
|
# Freeze the properties hash.
|
98
|
-
|
99
|
-
|
100
|
-
|
98
|
+
def freeze
|
99
|
+
@properties.freeze; self
|
100
|
+
end
|
101
101
|
|
102
102
|
# Returns +true+ if the properties hash has been frozen.
|
103
103
|
def frozen?
|
@@ -162,7 +162,7 @@ module Neo4j
|
|
162
162
|
end
|
163
163
|
|
164
164
|
def init_on_create(*)
|
165
|
-
self
|
165
|
+
self._classname = self.class.to_s
|
166
166
|
write_default_attributes
|
167
167
|
write_changed_attributes
|
168
168
|
write_changed_relationships
|
@@ -190,7 +190,7 @@ module Neo4j
|
|
190
190
|
# Ensure any defaults are stored in the DB
|
191
191
|
def write_default_attributes
|
192
192
|
attribute_defaults.each do |attribute, value|
|
193
|
-
write_attribute(attribute, Neo4j::TypeConverters.convert(value, attribute, self.class)) unless changed_attributes.has_key?(attribute) || _java_node.has_property?(attribute)
|
193
|
+
write_attribute(attribute, Neo4j::TypeConverters.convert(value, attribute, self.class, false)) unless changed_attributes.has_key?(attribute) || _java_node.has_property?(attribute)
|
194
194
|
end
|
195
195
|
end
|
196
196
|
|
@@ -262,7 +262,7 @@ module Neo4j
|
|
262
262
|
super(@record.errors.full_messages.join(", "))
|
263
263
|
end
|
264
264
|
end
|
265
|
-
|
266
|
-
|
265
|
+
end
|
266
|
+
end
|
267
267
|
end
|
268
268
|
|
data/lib/neo4j/rails/rails.rb
CHANGED
@@ -11,6 +11,7 @@ require 'neo4j/rails/validations'
|
|
11
11
|
require 'neo4j/rails/callbacks'
|
12
12
|
require 'neo4j/rails/observer'
|
13
13
|
require 'neo4j/rails/compositions'
|
14
|
+
require 'neo4j/rails/accept_id'
|
14
15
|
require 'neo4j/rails/timestamps'
|
15
16
|
require 'neo4j/rails/serialization'
|
16
17
|
require 'neo4j/rails/attributes'
|
data/lib/neo4j/rails/railtie.rb
CHANGED
@@ -15,7 +15,10 @@ module Neo4j
|
|
15
15
|
# Starting Neo after :load_config_initializers allows apps to
|
16
16
|
# register migrations in config/initializers
|
17
17
|
initializer "neo4j.start", :after => :load_config_initializers do |app|
|
18
|
-
|
18
|
+
cfg = app.config.neo4j
|
19
|
+
# Set Rails specific defaults
|
20
|
+
cfg.storage_path = "#{app.config.root}/db/neo4j-#{::Rails.env}" unless cfg.storage_path
|
21
|
+
Neo4j::Config.setup.merge!(cfg.to_hash)
|
19
22
|
end
|
20
23
|
|
21
24
|
# Instantitate any registered observers after Rails initialization and
|
@@ -151,17 +151,20 @@ module Neo4j
|
|
151
151
|
def create()
|
152
152
|
begin
|
153
153
|
# prevent calling create twice
|
154
|
-
@start_node.
|
155
|
-
@end_node.
|
154
|
+
@start_node.add_unpersisted_outgoing_rel(type, self)
|
155
|
+
@end_node.add_unpersisted_incoming_rel(type, self)
|
156
156
|
|
157
|
-
_persist_start_node
|
158
|
-
_persist_end_node
|
157
|
+
return unless _persist_start_node && _persist_end_node
|
159
158
|
|
160
159
|
@_java_rel = Neo4j::Relationship.new(type, start_node, end_node)
|
161
160
|
Neo4j::IdentityMap.add(@_java_rel, self)
|
162
161
|
init_on_create
|
163
162
|
clear_changes
|
164
|
-
|
163
|
+
|
164
|
+
@start_node.rm_unpersisted_outgoing_rel(type, self)
|
165
|
+
@end_node.rm_unpersisted_incoming_rel(type, self)
|
166
|
+
|
167
|
+
end unless @end_node.nil? or @start_node.nil?
|
165
168
|
true
|
166
169
|
end
|
167
170
|
|
@@ -170,18 +173,14 @@ module Neo4j
|
|
170
173
|
end
|
171
174
|
|
172
175
|
def _persist_start_node
|
173
|
-
|
174
|
-
# not sure if this can happen - probably a bug
|
175
|
-
raise "Can't save start_node #{@start_node} id #{@start_node.id}"
|
176
|
-
end
|
176
|
+
(!@start_node.persisted? || @start_node.relationships_changed?) ? @start_node.save : true
|
177
177
|
end
|
178
178
|
|
179
179
|
def _persist_end_node
|
180
|
-
|
181
|
-
raise "Can't save end_node #{@end_node} id #{@end_node.id}"
|
182
|
-
end
|
180
|
+
(!@end_node.persisted? || @end_node.relationships_changed?) ? @end_node.save : true
|
183
181
|
end
|
184
182
|
|
183
|
+
|
185
184
|
def init_on_create(*)
|
186
185
|
#self["_classname"] = self.class.to_s
|
187
186
|
write_default_attributes
|
@@ -21,7 +21,8 @@ module Neo4j
|
|
21
21
|
|
22
22
|
# Initialize a Node with a set of properties (or empty if nothing is passed)
|
23
23
|
def initialize(*args)
|
24
|
-
@
|
24
|
+
@properties_before_type_cast=java.util.HashMap.new
|
25
|
+
@type = args[0].to_s
|
25
26
|
self.start_node = args[1]
|
26
27
|
self.end_node = args[2]
|
27
28
|
attributes = args[3]
|
@@ -39,11 +40,15 @@ module Neo4j
|
|
39
40
|
|
40
41
|
|
41
42
|
alias_method :get_other_node, :other_node # so it looks like the java version
|
42
|
-
|
43
|
+
|
44
|
+
def rel_type
|
45
|
+
persisted? ? _java_entity.rel_type : @type
|
46
|
+
end
|
47
|
+
|
43
48
|
def to_s
|
44
49
|
"id: #{self.object_id} start_node: #{start_node.id} end_node: #{end_node.id} type:#{@type}"
|
45
50
|
end
|
46
|
-
|
51
|
+
|
47
52
|
def id
|
48
53
|
_java_rel.nil? || neo_id.nil? ? nil : neo_id.to_s
|
49
54
|
end
|
@@ -111,7 +116,7 @@ module Neo4j
|
|
111
116
|
def _all
|
112
117
|
_indexer.find(:_classname => self)
|
113
118
|
end
|
114
|
-
|
119
|
+
|
115
120
|
def load(*ids) # TODO Copied from finders.rb
|
116
121
|
result = ids.map { |id| entity_load(id) }
|
117
122
|
if ids.length == 1
|
@@ -9,7 +9,6 @@ module Neo4j
|
|
9
9
|
#
|
10
10
|
class NodesDSL
|
11
11
|
include Enumerable
|
12
|
-
include Neo4j::Paginate
|
13
12
|
|
14
13
|
def initialize(storage, dir)
|
15
14
|
@storage = storage
|
@@ -51,7 +50,14 @@ module Neo4j
|
|
51
50
|
|
52
51
|
# Adds a new node to the relationship
|
53
52
|
def <<(other)
|
54
|
-
|
53
|
+
if other.is_a?(String)
|
54
|
+
# this is typically called in an assignment operator, person.friends = ['42', '32']
|
55
|
+
node = Neo4j::Node.load(other)
|
56
|
+
@storage.create_relationship_to(node, @dir) unless all.include?(node)
|
57
|
+
else
|
58
|
+
# allow multiple relationships to the same node
|
59
|
+
@storage.create_relationship_to(other, @dir)
|
60
|
+
end
|
55
61
|
self
|
56
62
|
end
|
57
63
|
|
@@ -166,8 +172,8 @@ module Neo4j
|
|
166
172
|
|
167
173
|
alias :length :size
|
168
174
|
|
169
|
-
def each
|
170
|
-
@storage.each_node(@dir
|
175
|
+
def each
|
176
|
+
@storage.each_node(@dir) {|n| yield n} # Why passing the &block through doesn't work on JRuby 1.9?
|
171
177
|
end
|
172
178
|
|
173
179
|
def delete(*nodes)
|
@@ -185,7 +191,11 @@ module Neo4j
|
|
185
191
|
def to_s
|
186
192
|
"Node dir: #{@dir}, #{@storage}"
|
187
193
|
end
|
188
|
-
|
194
|
+
|
195
|
+
def rel_changed?
|
196
|
+
@storage.persisted?
|
197
|
+
end
|
198
|
+
|
189
199
|
protected
|
190
200
|
|
191
201
|
|
@@ -30,6 +30,9 @@ module Neo4j
|
|
30
30
|
@_relationships[decl_rels.rel_type.to_sym] ||= Storage.new(self, decl_rels.rel_type, decl_rels)
|
31
31
|
end
|
32
32
|
|
33
|
+
def _storage_for(rel_type) #:nodoc:
|
34
|
+
@_relationships[rel_type.to_sym]
|
35
|
+
end
|
33
36
|
|
34
37
|
# If the node is persisted and it does not have any unsaved relationship it returns a Neo4j::NodeTraverser.
|
35
38
|
# Otherwise it will return a NodesDSL which behaves like the Neo4j::NodeTraverser except that it does not
|
@@ -66,8 +69,12 @@ module Neo4j
|
|
66
69
|
# node.rels(:foo) #=> [node2] - incoming and outgoing
|
67
70
|
#
|
68
71
|
def rels(*rel_types)
|
69
|
-
|
70
|
-
|
72
|
+
if rel_types.empty?
|
73
|
+
AllRelsDsl.new(@_relationships, _java_node)
|
74
|
+
else
|
75
|
+
storage = _create_or_get_storage(rel_types.first)
|
76
|
+
RelsDSL.new(storage)
|
77
|
+
end
|
71
78
|
end
|
72
79
|
|
73
80
|
def add_outgoing_rel(rel_type, rel) #:nodoc:
|
@@ -86,6 +93,39 @@ module Neo4j
|
|
86
93
|
_create_or_get_storage(rel_type).rm_outgoing_rel(rel)
|
87
94
|
end
|
88
95
|
|
96
|
+
def rm_outgoing_rel(rel_type, rel) #:nodoc:
|
97
|
+
_create_or_get_storage(rel_type).rm_outgoing_rel(rel)
|
98
|
+
end
|
99
|
+
|
100
|
+
def add_unpersisted_incoming_rel(rel_type, rel) #:nodoc
|
101
|
+
if (storage = _create_or_get_storage(rel_type))
|
102
|
+
# move the relationship since we are now about to store the relationship
|
103
|
+
storage.add_unpersisted_incoming_rel(rel)
|
104
|
+
storage.rm_incoming_rel(rel)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def add_unpersisted_outgoing_rel(rel_type, rel) #:nodoc
|
109
|
+
if (storage = _create_or_get_storage(rel_type))
|
110
|
+
# move the relationship since we are now about to store the relationship
|
111
|
+
storage.add_unpersisted_outgoing_rel(rel)
|
112
|
+
storage.rm_outgoing_rel(rel)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def rm_unpersisted_outgoing_rel(rel_type, rel) #:nodoc
|
117
|
+
if (storage = _storage_for(rel_type))
|
118
|
+
storage.rm_unpersisted_outgoing_rel(rel)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def rm_unpersisted_incoming_rel(rel_type, rel) #:nodoc
|
123
|
+
if (storage = _storage_for(rel_type))
|
124
|
+
storage.rm_unpersisted_incoming_rel(rel)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
|
89
129
|
end
|
90
130
|
end
|
91
131
|
end
|