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
@@ -1,51 +1,128 @@
|
|
1
1
|
module Neo4j
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
2
|
+
module Rails
|
3
|
+
module Mapping
|
4
|
+
module Property
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
|
9
|
+
def has_n(*args)
|
10
|
+
options = args.extract_options!
|
11
|
+
define_has_n_methods_for(args.first, options)
|
12
|
+
end
|
13
|
+
|
14
|
+
def has_one(*args)
|
15
|
+
options = args.extract_options!
|
16
|
+
define_has_one_methods_for(args.first, options)
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
def define_has_one_methods_for(rel_type, options)
|
21
|
+
unless method_defined?(rel_type)
|
22
|
+
class_eval <<-RUBY, __FILE__, __LINE__
|
23
|
+
def #{rel_type}
|
24
|
+
dsl = _decl_rels_for(:'#{rel_type}')
|
25
|
+
storage = _create_or_get_storage_for_decl_rels(dsl)
|
26
|
+
storage.single_node(dsl.dir)
|
27
|
+
end
|
28
|
+
RUBY
|
29
|
+
end
|
30
|
+
|
31
|
+
unless method_defined?("#{rel_type}_rel")
|
32
|
+
class_eval <<-RUBY, __FILE__, __LINE__
|
33
|
+
def #{rel_type}_rel
|
34
|
+
dsl = _decl_rels_for(:'#{rel_type}')
|
35
|
+
storage = _create_or_get_storage_for_decl_rels(dsl)
|
36
|
+
storage.single_relationship(dsl.dir)
|
37
|
+
end
|
38
|
+
RUBY
|
39
|
+
end
|
40
|
+
|
41
|
+
unless method_defined?("#{rel_type}=".to_sym)
|
42
|
+
class_eval <<-RUBY, __FILE__, __LINE__
|
43
|
+
def #{rel_type}=(other)
|
44
|
+
dsl = _decl_rels_for(:'#{rel_type}')
|
45
|
+
storage = _create_or_get_storage_for_decl_rels(dsl)
|
46
|
+
rel = storage.single_relationship(dsl.dir)
|
47
|
+
rel && rel.destroy
|
48
|
+
storage.create_relationship_to(other, dsl.dir)
|
49
|
+
end
|
50
|
+
RUBY
|
51
|
+
end
|
52
|
+
_decl_rels[rel_type.to_sym] = Neo4j::HasN::DeclRelationshipDsl.new(rel_type, true, self)
|
53
|
+
end
|
54
|
+
|
55
|
+
def define_has_n_methods_for(rel_type, options)
|
56
|
+
unless method_defined?(rel_type)
|
57
|
+
class_eval <<-RUBY, __FILE__, __LINE__
|
58
|
+
def #{rel_type}
|
59
|
+
dsl = _decl_rels_for(:'#{rel_type}')
|
60
|
+
storage = _create_or_get_storage_for_decl_rels(dsl)
|
61
|
+
NodesDSL.new(storage, dsl.dir)
|
62
|
+
end
|
63
|
+
RUBY
|
64
|
+
end
|
65
|
+
|
66
|
+
unless method_defined?("#{rel_type}_rels".to_sym)
|
67
|
+
class_eval <<-RUBY, __FILE__, __LINE__
|
68
|
+
def #{rel_type}_rels
|
69
|
+
dsl = _decl_rels_for(:'#{rel_type}')
|
70
|
+
storage = _create_or_get_storage_for_decl_rels(dsl)
|
71
|
+
RelsDSL.new(storage, dsl.dir)
|
72
|
+
end
|
73
|
+
RUBY
|
74
|
+
end
|
75
|
+
|
76
|
+
instance_eval <<-RUBY, __FILE__, __LINE__
|
77
|
+
def #{rel_type}
|
78
|
+
_decl_rels[:'#{rel_type}'].rel_type.to_s
|
79
|
+
end
|
80
|
+
RUBY
|
81
|
+
|
82
|
+
_decl_rels[rel_type.to_sym] = Neo4j::HasN::DeclRelationshipDsl.new(rel_type, false, self)
|
83
|
+
end
|
84
|
+
|
85
|
+
# Handles options for the property
|
86
|
+
#
|
87
|
+
# Set the property type :type => Time
|
88
|
+
# Set a default :default => "default"
|
89
|
+
# Property must be there :null => false
|
90
|
+
# Property has a length limit :limit => 128
|
91
|
+
def property(*args)
|
92
|
+
options = args.extract_options!
|
93
|
+
args.each do |property_sym|
|
94
|
+
property_setup(property_sym, options)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
protected
|
99
|
+
def property_setup(property, options)
|
100
|
+
_decl_props[property] = options
|
101
|
+
handle_property_options_for(property, options)
|
102
|
+
define_property_methods_for(property, options)
|
103
|
+
end
|
104
|
+
|
105
|
+
def handle_property_options_for(property, options)
|
106
|
+
attribute_defaults[property.to_s] = options[:default] if options.has_key?(:default)
|
107
|
+
|
31
108
|
if options.has_key?(:null) && options[:null] === false
|
32
109
|
validates(property, :non_nil => true, :on => :create)
|
33
110
|
validates(property, :non_nil => true, :on => :update)
|
34
111
|
end
|
35
112
|
validates(property, :length => { :maximum => options[:limit] }) if options[:limit]
|
36
113
|
end
|
37
|
-
|
114
|
+
|
38
115
|
def define_property_methods_for(property, options)
|
39
116
|
unless method_defined?(property)
|
40
117
|
class_eval <<-RUBY, __FILE__, __LINE__
|
41
118
|
def #{property}
|
42
119
|
send(:[], "#{property}")
|
43
120
|
end
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
121
|
+
RUBY
|
122
|
+
end
|
123
|
+
|
124
|
+
unless method_defined?("#{property}=".to_sym)
|
125
|
+
class_eval <<-RUBY, __FILE__, __LINE__
|
49
126
|
def #{property}=(value)
|
50
127
|
send(:[]=, "#{property}", value)
|
51
128
|
end
|
data/lib/neo4j/rails/model.rb
CHANGED
@@ -3,6 +3,7 @@ module Neo4j
|
|
3
3
|
class Model
|
4
4
|
include Neo4j::NodeMixin
|
5
5
|
|
6
|
+
|
6
7
|
# Initialize a Node with a set of properties (or empty if nothing is passed)
|
7
8
|
def initialize(attributes = {})
|
8
9
|
reset_attributes
|
@@ -14,10 +15,15 @@ module Neo4j
|
|
14
15
|
neo_id.nil? ? nil : neo_id.to_s
|
15
16
|
end
|
16
17
|
|
18
|
+
def hash
|
19
|
+
persisted? ? _java_entity.neo_id.hash : super
|
20
|
+
end
|
21
|
+
|
17
22
|
def to_param
|
18
23
|
persisted? ? neo_id.to_s : nil
|
19
24
|
end
|
20
25
|
|
26
|
+
|
21
27
|
# Returns an Enumerable of all (primary) key attributes
|
22
28
|
# or nil if model.persisted? is false
|
23
29
|
def to_key
|
@@ -57,6 +63,10 @@ module Neo4j
|
|
57
63
|
end
|
58
64
|
end
|
59
65
|
|
66
|
+
def entity_load(id)
|
67
|
+
Neo4j::Node.load(id)
|
68
|
+
end
|
69
|
+
|
60
70
|
##
|
61
71
|
# Determines whether to use Time.local (using :local) or Time.utc (using :utc) when pulling
|
62
72
|
# dates and times from the database. This is set to :local by default.
|
@@ -5,7 +5,7 @@ module Neo4j
|
|
5
5
|
|
6
6
|
included do
|
7
7
|
extend TxMethods
|
8
|
-
tx_methods :destroy, :create, :update, :update_nested_attributes
|
8
|
+
tx_methods :destroy, :create, :update, :update_nested_attributes, :delete
|
9
9
|
end
|
10
10
|
|
11
11
|
# Persist the object to the database. Validations and Callbacks are included
|
@@ -53,7 +53,7 @@ module Neo4j
|
|
53
53
|
|
54
54
|
# Returns true if the object was destroyed.
|
55
55
|
def destroyed?()
|
56
|
-
@_deleted
|
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.
|
@@ -108,13 +108,19 @@ module Neo4j
|
|
108
108
|
# Initialize a model and set a bunch of attributes at the same time. Returns
|
109
109
|
# the object whether saved successfully or not.
|
110
110
|
def create(*args)
|
111
|
-
new(*args).tap
|
111
|
+
new(*args).tap do |o|
|
112
|
+
yield o if block_given?
|
113
|
+
o.save
|
114
|
+
end
|
112
115
|
end
|
113
116
|
|
114
117
|
# Same as #create, but raises an error if there is a problem during save.
|
115
118
|
# Returns the object whether saved successfully or not.
|
116
119
|
def create!(*args)
|
117
|
-
new(*args).tap
|
120
|
+
new(*args).tap do |o|
|
121
|
+
yield o if block_given?
|
122
|
+
o.save!
|
123
|
+
end
|
118
124
|
end
|
119
125
|
|
120
126
|
# Destroy each node in turn. Runs the destroy callbacks for each node.
|
data/lib/neo4j/rails/rails.rb
CHANGED
@@ -4,6 +4,7 @@ require 'neo4j/rails/transaction'
|
|
4
4
|
require 'neo4j/rails/railtie'
|
5
5
|
require 'neo4j/rails/validations/uniqueness'
|
6
6
|
require 'neo4j/rails/validations/non_nil'
|
7
|
+
require 'neo4j/rails/validations/associated'
|
7
8
|
require 'neo4j/rails/finders'
|
8
9
|
require 'neo4j/rails/mapping/property'
|
9
10
|
require 'neo4j/rails/validations'
|
@@ -12,8 +13,11 @@ require 'neo4j/rails/timestamps'
|
|
12
13
|
require 'neo4j/rails/serialization'
|
13
14
|
require 'neo4j/rails/attributes'
|
14
15
|
require 'neo4j/rails/persistence'
|
15
|
-
require 'neo4j/rails/relationships/
|
16
|
-
require 'neo4j/rails/relationships/
|
16
|
+
require 'neo4j/rails/relationships/storage'
|
17
|
+
require 'neo4j/rails/relationships/node_dsl'
|
18
|
+
require 'neo4j/rails/relationships/rels_dsl'
|
17
19
|
require 'neo4j/rails/relationships/relationships'
|
18
20
|
require 'neo4j/rails/model'
|
19
21
|
require 'neo4j/rails/lucene_connection_closer'
|
22
|
+
require 'neo4j/rails/rel_persistence'
|
23
|
+
require 'neo4j/rails/relationship'
|
@@ -0,0 +1,231 @@
|
|
1
|
+
module Neo4j
|
2
|
+
module Rails
|
3
|
+
module RelPersistence
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
extend TxMethods
|
8
|
+
tx_methods :destroy, :create, :update, :delete
|
9
|
+
end
|
10
|
+
|
11
|
+
|
12
|
+
# Persist the object to the database. Validations and Callbacks are included
|
13
|
+
# by default but validation can be disabled by passing :validate => false
|
14
|
+
# to #save.
|
15
|
+
def save(*)
|
16
|
+
create_or_update
|
17
|
+
end
|
18
|
+
|
19
|
+
# Persist the object to the database. Validations and Callbacks are included
|
20
|
+
# by default but validation can be disabled by passing :validate => false
|
21
|
+
# to #save!.
|
22
|
+
#
|
23
|
+
# Raises a RecordInvalidError if there is a problem during save.
|
24
|
+
def save!(*args)
|
25
|
+
unless save(*args)
|
26
|
+
raise RecordInvalidError.new(self)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Updates a single attribute and saves the record.
|
31
|
+
# This is especially useful for boolean flags on existing records. Also note that
|
32
|
+
#
|
33
|
+
# * Validation is skipped.
|
34
|
+
# * Callbacks are invoked.
|
35
|
+
# * Updates all the attributes that are dirty in this object.
|
36
|
+
#
|
37
|
+
def update_attribute(name, value)
|
38
|
+
respond_to?("#{name}=") ? send("#{name}=", value) : self[name] = value
|
39
|
+
save(:validate => false)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Removes the node from Neo4j and freezes the object.
|
43
|
+
def destroy
|
44
|
+
delete
|
45
|
+
freeze
|
46
|
+
end
|
47
|
+
|
48
|
+
# Same as #destroy but doesn't run destroy callbacks and doesn't freeze
|
49
|
+
# the object
|
50
|
+
def delete
|
51
|
+
del unless new_record?
|
52
|
+
set_deleted_properties
|
53
|
+
end
|
54
|
+
|
55
|
+
# Returns true if the object was destroyed.
|
56
|
+
def destroyed?()
|
57
|
+
@_deleted || Neo4j::Relationship._load(id).nil?
|
58
|
+
end
|
59
|
+
|
60
|
+
# Updates this resource with all the attributes from the passed-in Hash and requests that the record be saved.
|
61
|
+
# If saving fails because the resource is invalid then false will be returned.
|
62
|
+
def update_attributes(attributes)
|
63
|
+
self.attributes = attributes
|
64
|
+
save
|
65
|
+
end
|
66
|
+
|
67
|
+
# Same as #update_attributes, but raises an exception if saving fails.
|
68
|
+
def update_attributes!(attributes)
|
69
|
+
self.attributes = attributes
|
70
|
+
save!
|
71
|
+
end
|
72
|
+
|
73
|
+
# Reload the object from the DB.
|
74
|
+
def reload(options = nil)
|
75
|
+
clear_changes
|
76
|
+
reset_attributes
|
77
|
+
unless reload_from_database
|
78
|
+
set_deleted_properties
|
79
|
+
freeze
|
80
|
+
end
|
81
|
+
self
|
82
|
+
end
|
83
|
+
|
84
|
+
# Returns if the record is persisted, i.e. it’s not a new record and it was not destroyed
|
85
|
+
def persisted?
|
86
|
+
!new_record? && !destroyed?
|
87
|
+
end
|
88
|
+
|
89
|
+
# Returns true if the record hasn't been saved to Neo4j yet.
|
90
|
+
def new_record?
|
91
|
+
_java_rel.nil?
|
92
|
+
end
|
93
|
+
|
94
|
+
alias :new? :new_record?
|
95
|
+
|
96
|
+
# Freeze the properties hash.
|
97
|
+
def freeze
|
98
|
+
@properties.freeze; self
|
99
|
+
end
|
100
|
+
|
101
|
+
# Returns +true+ if the properties hash has been frozen.
|
102
|
+
def frozen?
|
103
|
+
reload
|
104
|
+
@properties.frozen?
|
105
|
+
end
|
106
|
+
|
107
|
+
module ClassMethods
|
108
|
+
# Initialize a model and set a bunch of attributes at the same time. Returns
|
109
|
+
# the object whether saved successfully or not.
|
110
|
+
def create(*args)
|
111
|
+
new(*args).tap do |o|
|
112
|
+
yield o if block_given?
|
113
|
+
o.save
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# Same as #create, but raises an error if there is a problem during save.
|
118
|
+
# Returns the object whether saved successfully or not.
|
119
|
+
def create!(*args)
|
120
|
+
new(*args).tap do |o|
|
121
|
+
yield o if block_given?
|
122
|
+
o.save!
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
# Destroy each node in turn. Runs the destroy callbacks for each node.
|
127
|
+
def destroy_all
|
128
|
+
all.each do |n|
|
129
|
+
n.destroy
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
protected
|
135
|
+
def create_or_update
|
136
|
+
result = persisted? ? update : create
|
137
|
+
unless result != false
|
138
|
+
Neo4j::Rails::Transaction.fail if Neo4j::Rails::Transaction.running?
|
139
|
+
false
|
140
|
+
else
|
141
|
+
true
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def update
|
146
|
+
write_changed_attributes
|
147
|
+
clear_changes
|
148
|
+
true
|
149
|
+
end
|
150
|
+
|
151
|
+
def create()
|
152
|
+
# prevent calling create twice
|
153
|
+
@start_node.rm_outgoing_rel(type, self)
|
154
|
+
@end_node.rm_incoming_rel(type, self)
|
155
|
+
|
156
|
+
_persist_start_node
|
157
|
+
_persist_end_node
|
158
|
+
|
159
|
+
@_java_rel = Neo4j::Relationship.new(type, start_node, end_node)
|
160
|
+
init_on_create
|
161
|
+
clear_changes
|
162
|
+
true
|
163
|
+
end
|
164
|
+
|
165
|
+
def _load(id)
|
166
|
+
Neo4j::Relationship.load(id)
|
167
|
+
end
|
168
|
+
|
169
|
+
def _persist_start_node
|
170
|
+
unless @start_node.persisted? || @start_node.save
|
171
|
+
# not sure if this can happen - probably a bug
|
172
|
+
raise "Can't save start_node #{@start_node} id #{@start_node.id}"
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def _persist_end_node
|
177
|
+
unless @end_node.persisted? || @end_node.save
|
178
|
+
raise "Can't save end_node #{@end_node} id #{@end_node.id}"
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
def init_on_create(*)
|
183
|
+
#self["_classname"] = self.class.to_s
|
184
|
+
write_default_attributes
|
185
|
+
write_changed_attributes
|
186
|
+
@_java_rel[:_classname] = self.class.to_s
|
187
|
+
end
|
188
|
+
|
189
|
+
def reset_attributes
|
190
|
+
@properties = {}
|
191
|
+
end
|
192
|
+
|
193
|
+
def reload_from_database
|
194
|
+
if reloaded = self.class.load(id)
|
195
|
+
send(:attributes=, reloaded.attributes, false)
|
196
|
+
end
|
197
|
+
reloaded
|
198
|
+
end
|
199
|
+
|
200
|
+
def set_deleted_properties
|
201
|
+
@_deleted = true
|
202
|
+
@_persisted = false
|
203
|
+
end
|
204
|
+
|
205
|
+
# Ensure any defaults are stored in the DB
|
206
|
+
def write_default_attributes
|
207
|
+
attribute_defaults.each do |attribute, value|
|
208
|
+
write_attribute(attribute, Neo4j::TypeConverters.convert(value, attribute, self.class)) unless changed_attributes.has_key?(attribute) || _java_rel.has_property?(attribute)
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
# Write attributes to the Neo4j DB only if they're altered
|
213
|
+
def write_changed_attributes
|
214
|
+
@properties.each do |attribute, value|
|
215
|
+
write_attribute(attribute, value) if changed_attributes.has_key?(attribute)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
class RecordInvalidError < RuntimeError
|
220
|
+
attr_reader :record
|
221
|
+
|
222
|
+
def initialize(record)
|
223
|
+
@record = record
|
224
|
+
super(@record.errors.full_messages.join(", "))
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
end
|
229
|
+
|
230
|
+
end
|
231
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
module Neo4j
|
2
|
+
module Rails
|
3
|
+
class Relationship
|
4
|
+
include Neo4j::RelationshipMixin
|
5
|
+
|
6
|
+
attr_reader :type
|
7
|
+
|
8
|
+
index :_classname
|
9
|
+
|
10
|
+
# Initialize a Node with a set of properties (or empty if nothing is passed)
|
11
|
+
def initialize(*args)
|
12
|
+
@type = args[0]
|
13
|
+
self.start_node = args[1]
|
14
|
+
self.end_node = args[2]
|
15
|
+
attributes = args[3]
|
16
|
+
reset_attributes
|
17
|
+
self.attributes = attributes if attributes.is_a?(Hash)
|
18
|
+
end
|
19
|
+
|
20
|
+
def other_node(node)
|
21
|
+
if persisted?
|
22
|
+
_java_rel.getOtherNode(node._java_node)
|
23
|
+
else
|
24
|
+
@start_node == (node._java_node || node) ? @end_node : @start_node
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
alias_method :get_other_node, :other_node # so it looks like the java version
|
30
|
+
|
31
|
+
def to_s
|
32
|
+
"id: #{self.object_id} start_node: #{start_node.id} end_node: #{end_node.id} type:#{@type}"
|
33
|
+
end
|
34
|
+
|
35
|
+
def id
|
36
|
+
_java_rel.nil? || neo_id.nil? ? nil : neo_id.to_s
|
37
|
+
end
|
38
|
+
|
39
|
+
def hash
|
40
|
+
persisted? ? _java_entity.neo_id.hash : super
|
41
|
+
end
|
42
|
+
|
43
|
+
def start_node
|
44
|
+
@start_node ||= _java_rel && _java_rel.start_node
|
45
|
+
end
|
46
|
+
|
47
|
+
def start_node=(node)
|
48
|
+
old = @start_node
|
49
|
+
@start_node = node
|
50
|
+
# TODO should raise exception if not persisted and changed
|
51
|
+
if old != @start_node
|
52
|
+
old && old.rm_outgoing_rel(type, self)
|
53
|
+
@start_node.class != Neo4j::Node && @start_node.add_outgoing_rel(type, self)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def end_node
|
58
|
+
@end_node ||= _java_rel && _java_rel.end_node
|
59
|
+
end
|
60
|
+
|
61
|
+
def end_node=(node)
|
62
|
+
old = @end_node
|
63
|
+
@end_node = node
|
64
|
+
# TODO should raise exception if not persisted and changed
|
65
|
+
if old != @end_node
|
66
|
+
old && old.rm_incoming_rel(type, self)
|
67
|
+
@end_node.class != Neo4j::Node && @end_node.add_incoming_rel(type, self)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def del
|
72
|
+
_java_rel.del
|
73
|
+
end
|
74
|
+
|
75
|
+
def reset_attributes
|
76
|
+
@properties = {}
|
77
|
+
end
|
78
|
+
|
79
|
+
# --------------------------------------
|
80
|
+
# Public Class Methods
|
81
|
+
# --------------------------------------
|
82
|
+
class << self
|
83
|
+
# NodeMixin overwrites the #new class method but it saves it as orig_new
|
84
|
+
# Here, we just get it back to normal
|
85
|
+
alias :new :orig_new
|
86
|
+
|
87
|
+
def entity_load(id)
|
88
|
+
Neo4j::Relationship.load(id)
|
89
|
+
end
|
90
|
+
|
91
|
+
|
92
|
+
def rule(*)
|
93
|
+
end
|
94
|
+
|
95
|
+
def _all
|
96
|
+
_indexer.find(:_classname => self)
|
97
|
+
end
|
98
|
+
|
99
|
+
def load(*ids) # TODO Copied from finders.rb
|
100
|
+
result = ids.map { |id| entity_load(id) }
|
101
|
+
if ids.length == 1
|
102
|
+
result.first
|
103
|
+
else
|
104
|
+
result
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
|
113
|
+
Relationship.class_eval do
|
114
|
+
extend ActiveModel::Translation
|
115
|
+
include RelPersistence # handles how to save, create and update the model
|
116
|
+
include Attributes # handles how to save and retrieve attributes
|
117
|
+
include Mapping::Property # allows some additional options on the #property class method
|
118
|
+
include Serialization # enable to_xml and to_json
|
119
|
+
include Timestamps # handle created_at, updated_at timestamp properties
|
120
|
+
include Validations # enable validations
|
121
|
+
include Callbacks # enable callbacks
|
122
|
+
include Finders # ActiveRecord style find
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
end
|