neo4j 2.0.0.alpha.5-java → 2.0.0.alpha.6-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/CHANGELOG +12 -0
- data/Gemfile +0 -4
- data/README.rdoc +106 -62
- data/lib/neo4j.rb +7 -33
- data/lib/neo4j/performance.rb +43 -0
- data/lib/neo4j/rails/accept_id.rb +19 -18
- data/lib/neo4j/rails/attributes.rb +366 -120
- data/lib/neo4j/rails/finders.rb +41 -15
- data/lib/neo4j/rails/has_n.rb +203 -0
- data/lib/neo4j/rails/identity.rb +25 -0
- data/lib/neo4j/rails/model.rb +65 -242
- data/lib/neo4j/rails/nested_attributes.rb +108 -0
- data/lib/neo4j/rails/node_persistance.rb +56 -0
- data/lib/neo4j/rails/observer.rb +0 -2
- data/lib/neo4j/rails/persistence.rb +32 -154
- data/lib/neo4j/rails/rack_middleware.rb +26 -2
- data/lib/neo4j/rails/rails.rb +9 -6
- data/lib/neo4j/rails/railtie.rb +1 -2
- data/lib/neo4j/rails/relationship.rb +18 -125
- data/lib/neo4j/rails/relationship_persistence.rb +107 -0
- data/lib/neo4j/rails/relationships/node_dsl.rb +72 -44
- data/lib/neo4j/rails/relationships/relationships.rb +187 -59
- data/lib/neo4j/rails/relationships/rels_dsl.rb +18 -17
- data/lib/neo4j/rails/relationships/storage.rb +19 -17
- data/lib/neo4j/rails/timestamps.rb +53 -51
- data/lib/neo4j/rails/transaction.rb +9 -1
- data/lib/neo4j/rails/validations/uniqueness.rb +1 -1
- data/lib/neo4j/rails/versioning/versioning.rb +2 -2
- data/lib/neo4j/version.rb +1 -1
- data/lib/orm_adapter/adapters/neo4j.rb +47 -46
- data/neo4j.gemspec +1 -1
- metadata +10 -69
- data/lib/neo4j/algo/algo.rb +0 -294
- data/lib/neo4j/batch/batch.rb +0 -4
- data/lib/neo4j/batch/indexer.rb +0 -109
- data/lib/neo4j/batch/inserter.rb +0 -179
- data/lib/neo4j/batch/rule_inserter.rb +0 -24
- data/lib/neo4j/batch/rule_node.rb +0 -72
- data/lib/neo4j/config.rb +0 -177
- data/lib/neo4j/core_ext/class/inheritable_attributes.rb +0 -12
- data/lib/neo4j/core_ext/class/rewrite_inheritable_attributes.rb +0 -170
- data/lib/neo4j/database.rb +0 -158
- data/lib/neo4j/equal.rb +0 -21
- data/lib/neo4j/event_handler.rb +0 -263
- data/lib/neo4j/has_list/class_methods.rb +0 -11
- data/lib/neo4j/has_list/has_list.rb +0 -3
- data/lib/neo4j/has_list/mapping.rb +0 -133
- data/lib/neo4j/has_n/class_methods.rb +0 -119
- data/lib/neo4j/has_n/decl_relationship_dsl.rb +0 -246
- data/lib/neo4j/has_n/has_n.rb +0 -3
- data/lib/neo4j/has_n/mapping.rb +0 -98
- data/lib/neo4j/identity_map.rb +0 -140
- data/lib/neo4j/index/class_methods.rb +0 -108
- data/lib/neo4j/index/index.rb +0 -39
- data/lib/neo4j/index/indexer.rb +0 -341
- data/lib/neo4j/index/indexer_registry.rb +0 -68
- data/lib/neo4j/index/lucene_query.rb +0 -256
- data/lib/neo4j/load.rb +0 -25
- data/lib/neo4j/migrations/class_methods.rb +0 -110
- data/lib/neo4j/migrations/extensions.rb +0 -58
- data/lib/neo4j/migrations/lazy_node_mixin.rb +0 -41
- data/lib/neo4j/migrations/migration.rb +0 -112
- data/lib/neo4j/migrations/migrations.rb +0 -6
- data/lib/neo4j/migrations/node_mixin.rb +0 -80
- data/lib/neo4j/migrations/ref_node_wrapper.rb +0 -32
- data/lib/neo4j/model.rb +0 -4
- data/lib/neo4j/neo4j.rb +0 -216
- data/lib/neo4j/node.rb +0 -270
- data/lib/neo4j/node_mixin/class_methods.rb +0 -51
- data/lib/neo4j/node_mixin/node_mixin.rb +0 -141
- data/lib/neo4j/paginated.rb +0 -23
- data/lib/neo4j/property/class_methods.rb +0 -79
- data/lib/neo4j/property/property.rb +0 -111
- data/lib/neo4j/rails/mapping/property.rb +0 -183
- data/lib/neo4j/rails/rel_persistence.rb +0 -237
- data/lib/neo4j/relationship.rb +0 -239
- data/lib/neo4j/relationship_mixin/class_methods.rb +0 -36
- data/lib/neo4j/relationship_mixin/relationship_mixin.rb +0 -142
- data/lib/neo4j/relationship_set.rb +0 -58
- data/lib/neo4j/rels/rels.rb +0 -110
- data/lib/neo4j/rels/traverser.rb +0 -102
- data/lib/neo4j/rule/class_methods.rb +0 -201
- data/lib/neo4j/rule/event_listener.rb +0 -66
- data/lib/neo4j/rule/functions/count.rb +0 -43
- data/lib/neo4j/rule/functions/function.rb +0 -74
- data/lib/neo4j/rule/functions/functions.rb +0 -3
- data/lib/neo4j/rule/functions/sum.rb +0 -29
- data/lib/neo4j/rule/rule.rb +0 -150
- data/lib/neo4j/rule/rule_node.rb +0 -217
- data/lib/neo4j/to_java.rb +0 -31
- data/lib/neo4j/transaction.rb +0 -73
- data/lib/neo4j/traversal/filter_predicate.rb +0 -25
- data/lib/neo4j/traversal/prune_evaluator.rb +0 -14
- data/lib/neo4j/traversal/rel_expander.rb +0 -31
- data/lib/neo4j/traversal/traversal.rb +0 -141
- data/lib/neo4j/traversal/traverser.rb +0 -284
- data/lib/neo4j/type_converters/type_converters.rb +0 -288
data/lib/neo4j/rails/finders.rb
CHANGED
@@ -6,11 +6,26 @@ module Neo4j
|
|
6
6
|
module Finders
|
7
7
|
extend ActiveSupport::Concern
|
8
8
|
|
9
|
+
|
10
|
+
def reachable_from_ref_node?
|
11
|
+
# All relationships are reachable
|
12
|
+
respond_to?(:_java_rel) || Neo4j::Algo.all_path(self.class.ref_node_for_class, self).outgoing(self.class).outgoing(:_all).first != nil
|
13
|
+
end
|
14
|
+
|
9
15
|
included do
|
10
|
-
rule(:_all, :functions => Neo4j::Rule::Functions::
|
16
|
+
rule(:_all, :functions => Neo4j::Wrapper::Rule::Functions::Size.new) if respond_to?(:rule)
|
11
17
|
end
|
12
18
|
|
13
19
|
module ClassMethods
|
20
|
+
|
21
|
+
def index_prefix
|
22
|
+
return "" unless Neo4j.running?
|
23
|
+
return "" unless respond_to?(:ref_node_for_class)
|
24
|
+
ref_node = ref_node_for_class.wrapper
|
25
|
+
prefix = ref_node.respond_to?(:index_prefix) ? ref_node.send(:index_prefix) : ref_node[:name]
|
26
|
+
prefix ? prefix + "_" : ""
|
27
|
+
end
|
28
|
+
|
14
29
|
# overwrite the index method to add find_by_xxx class methods
|
15
30
|
def index(*args)
|
16
31
|
field = args.first
|
@@ -40,7 +55,7 @@ module Neo4j
|
|
40
55
|
|
41
56
|
# load an id or array of ids from the database
|
42
57
|
def load(*ids)
|
43
|
-
result = ids.map { |id|
|
58
|
+
result = ids.map { |id| load_entity(id) }
|
44
59
|
if ids.length == 1
|
45
60
|
result.first
|
46
61
|
else
|
@@ -48,6 +63,8 @@ module Neo4j
|
|
48
63
|
end
|
49
64
|
end
|
50
65
|
|
66
|
+
Neo4j::Wrapper::Find.send(:alias_method, :_wrapper_find, :find)
|
67
|
+
|
51
68
|
# Behave like the ActiveRecord query interface
|
52
69
|
#
|
53
70
|
# === Example
|
@@ -68,18 +85,18 @@ module Neo4j
|
|
68
85
|
# Model.find(:all, :conditions => "name: test")
|
69
86
|
# Model.find(:all, :conditions => { :name => "test" })
|
70
87
|
#
|
71
|
-
def find(*args)
|
88
|
+
def find(*args, &block)
|
72
89
|
case args.first
|
73
90
|
when :all, :first
|
74
91
|
kind = args.shift
|
75
|
-
send(kind, *args)
|
92
|
+
send(kind, *args, &block)
|
76
93
|
when "0", 0, nil
|
77
94
|
nil
|
78
95
|
else
|
79
96
|
if convertable_to_id?(args.first)
|
80
97
|
find_with_ids(*args)
|
81
98
|
else
|
82
|
-
first(*args)
|
99
|
+
first(*args, &block)
|
83
100
|
end
|
84
101
|
end
|
85
102
|
end
|
@@ -124,7 +141,7 @@ module Neo4j
|
|
124
141
|
find_or(:new, attrs, &block)
|
125
142
|
end
|
126
143
|
|
127
|
-
def all(*args)
|
144
|
+
def all(*args, &block)
|
128
145
|
if !conditions_in?(*args)
|
129
146
|
# use the _all rule to recover all the stored instances of this node
|
130
147
|
_all
|
@@ -134,18 +151,18 @@ module Neo4j
|
|
134
151
|
if ids
|
135
152
|
[find_with_ids(ids)].flatten
|
136
153
|
else
|
137
|
-
find_with_indexer(*args)
|
154
|
+
find_with_indexer(*args, &block)
|
138
155
|
end
|
139
156
|
end
|
140
157
|
end
|
141
158
|
|
142
|
-
def first(*args)
|
143
|
-
all(*args).first
|
159
|
+
def first(*args, &block)
|
160
|
+
all(*args, &block).first
|
144
161
|
end
|
145
162
|
|
146
163
|
def last(*args)
|
147
164
|
a = all(*args)
|
148
|
-
a.empty? ? nil : a[
|
165
|
+
a.empty? ? nil : a[all.size - 1]
|
149
166
|
end
|
150
167
|
|
151
168
|
def count
|
@@ -201,14 +218,23 @@ module Neo4j
|
|
201
218
|
end
|
202
219
|
|
203
220
|
def findable?(entity)
|
204
|
-
entity.is_a?
|
221
|
+
entity.is_a?(self) and entity.reachable_from_ref_node?
|
205
222
|
end
|
206
223
|
|
207
|
-
def find_with_indexer(*args)
|
208
|
-
hits
|
224
|
+
def find_with_indexer(*args, &block)
|
225
|
+
hits = if args.first.is_a?(Hash) && args.first.include?(:conditions)
|
226
|
+
params = args.first.clone
|
227
|
+
params.delete(:conditions)
|
228
|
+
raise "ARGS #{args.inspect}" if args.size > 1
|
229
|
+
_wrapper_find(args.first[:conditions], params, &block)
|
230
|
+
else
|
231
|
+
_wrapper_find(*args, &block)
|
232
|
+
end
|
233
|
+
|
234
|
+
|
209
235
|
# We need to save this so that the Rack Neo4j::Rails:LuceneConnection::Closer can close it
|
210
236
|
Thread.current[:neo4j_lucene_connection] ||= []
|
211
|
-
Thread.current[:neo4j_lucene_connection] << hits
|
237
|
+
Thread.current[:neo4j_lucene_connection] << hits if hits.respond_to?(:close)
|
212
238
|
hits
|
213
239
|
end
|
214
240
|
|
@@ -222,7 +248,7 @@ module Neo4j
|
|
222
248
|
#
|
223
249
|
# @return [ Node ] The first or new node.
|
224
250
|
def find_or(method, attrs = {}, &block)
|
225
|
-
first(
|
251
|
+
first(attrs) || send(method, attrs, &block)
|
226
252
|
end
|
227
253
|
end
|
228
254
|
end
|
@@ -0,0 +1,203 @@
|
|
1
|
+
module Neo4j
|
2
|
+
module Rails
|
3
|
+
module HasN
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
module ClassMethods
|
7
|
+
|
8
|
+
# Create a number of methods similar to active record has_many.
|
9
|
+
# The first one returns an Neo4j::Rails::Relationships::NodesDSL
|
10
|
+
# the second generate method (with the _rels postfix) returns a
|
11
|
+
# Neo4j::Rails::Relationships::RelsDSL
|
12
|
+
#
|
13
|
+
# See also Neo4j::NodeMixin#has_n which only work with persisted relationships.
|
14
|
+
#
|
15
|
+
# @example
|
16
|
+
# class Thing
|
17
|
+
# has_n(:things)
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# t = Thing.new
|
21
|
+
# t.things << Thing.new << OtherClass.new
|
22
|
+
# t.save # saves all nodes and relationships
|
23
|
+
#
|
24
|
+
# @example declare a to relationship
|
25
|
+
# class Company
|
26
|
+
# has_n(:employees).to(Person)
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# c = Company.new
|
30
|
+
# c.employees << Person.new << Person.new(:name => 'kalle')
|
31
|
+
#
|
32
|
+
# @example creates a new person and relationship
|
33
|
+
# c.employees.build(:name => 'sune')
|
34
|
+
#
|
35
|
+
# @example creates a new person and relationship and persist it
|
36
|
+
# c.employees.create(:name => 'sune')
|
37
|
+
#
|
38
|
+
# @example delete all nodes and relationships
|
39
|
+
# c.employees.destroy_all
|
40
|
+
#
|
41
|
+
# @example access the relationships and destroy them
|
42
|
+
# c.employees_rels.destroy_all
|
43
|
+
#
|
44
|
+
# @example advanced traversal, using Neo4j::Core::Traversal
|
45
|
+
# c._outgoing(Company.employees).outgoing(:friends).depth.each{ }
|
46
|
+
#
|
47
|
+
# @see Neo4j::Rails::Relationships::NodesDSL
|
48
|
+
def has_n(*args)
|
49
|
+
options = args.extract_options!
|
50
|
+
define_has_n_methods_for(args.first, options)
|
51
|
+
end
|
52
|
+
|
53
|
+
# Declares ONE incoming or outgoing relationship
|
54
|
+
#
|
55
|
+
# @example
|
56
|
+
# class Person
|
57
|
+
# has_one(:friend).to(OtherClass)
|
58
|
+
# end
|
59
|
+
#
|
60
|
+
# @example
|
61
|
+
# person.best_friend = my_friend
|
62
|
+
#
|
63
|
+
# @example
|
64
|
+
# person.best_friend # => my_friend
|
65
|
+
#
|
66
|
+
# @example
|
67
|
+
# person.build_best_friend(:name => 'foo')
|
68
|
+
#
|
69
|
+
# @example
|
70
|
+
# person.create_best_friend(:name => 'foo')
|
71
|
+
#
|
72
|
+
# @example
|
73
|
+
# person.create_best_friend!(:name => 'foo')
|
74
|
+
#
|
75
|
+
# @notice when using the <tt>build_</tt> and <tt>create_</tt> methods you <b>must</b> specify a <tt>to</to> relationship as done above in the Person example
|
76
|
+
def has_one(*args)
|
77
|
+
options = args.extract_options!
|
78
|
+
define_has_one_methods_for(args.first, options)
|
79
|
+
end
|
80
|
+
|
81
|
+
protected
|
82
|
+
|
83
|
+
def define_has_one_methods_for(rel_type, options)
|
84
|
+
unless method_defined?(rel_type)
|
85
|
+
class_eval <<-RUBY, __FILE__, __LINE__
|
86
|
+
def #{rel_type}
|
87
|
+
dsl = _decl_rels_for(:'#{rel_type}')
|
88
|
+
storage = _create_or_get_storage_for_decl_rels(dsl)
|
89
|
+
storage.single_node(dsl.dir)
|
90
|
+
end
|
91
|
+
RUBY
|
92
|
+
end
|
93
|
+
|
94
|
+
unless method_defined?("#{rel_type}_rel")
|
95
|
+
class_eval <<-RUBY, __FILE__, __LINE__
|
96
|
+
def #{rel_type}_rel
|
97
|
+
dsl = _decl_rels_for(:'#{rel_type}')
|
98
|
+
storage = _create_or_get_storage_for_decl_rels(dsl)
|
99
|
+
storage.single_relationship(dsl.dir)
|
100
|
+
end
|
101
|
+
RUBY
|
102
|
+
end
|
103
|
+
|
104
|
+
unless method_defined?("#{rel_type}=".to_sym)
|
105
|
+
class_eval <<-RUBY, __FILE__, __LINE__
|
106
|
+
def #{rel_type}=(other)
|
107
|
+
dsl = _decl_rels_for(:'#{rel_type}')
|
108
|
+
storage = _create_or_get_storage_for_decl_rels(dsl)
|
109
|
+
storage.destroy_single_relationship(dsl.dir)
|
110
|
+
storage.create_relationship_to(other, dsl.dir) if other
|
111
|
+
end
|
112
|
+
RUBY
|
113
|
+
end
|
114
|
+
|
115
|
+
unless method_defined?("build_#{rel_type}".to_sym)
|
116
|
+
class_eval <<-RUBY, __FILE__, __LINE__
|
117
|
+
def build_#{rel_type}(attr)
|
118
|
+
dsl = _decl_rels_for(:'#{rel_type}')
|
119
|
+
storage = _create_or_get_storage_for_decl_rels(dsl)
|
120
|
+
NodesDSL.new(storage, dsl.dir).build(attr)
|
121
|
+
end
|
122
|
+
RUBY
|
123
|
+
end
|
124
|
+
|
125
|
+
unless method_defined?("create_#{rel_type}".to_sym)
|
126
|
+
class_eval <<-RUBY, __FILE__, __LINE__
|
127
|
+
def create_#{rel_type}(attr)
|
128
|
+
dsl = _decl_rels_for(:'#{rel_type}')
|
129
|
+
storage = _create_or_get_storage_for_decl_rels(dsl)
|
130
|
+
NodesDSL.new(storage, dsl.dir).create(attr)
|
131
|
+
end
|
132
|
+
RUBY
|
133
|
+
end
|
134
|
+
|
135
|
+
unless method_defined?("create_#{rel_type}!".to_sym)
|
136
|
+
class_eval <<-RUBY, __FILE__, __LINE__
|
137
|
+
def create_#{rel_type}!(attr)
|
138
|
+
dsl = _decl_rels_for(:'#{rel_type}')
|
139
|
+
storage = _create_or_get_storage_for_decl_rels(dsl)
|
140
|
+
NodesDSL.new(storage, dsl.dir).create!(attr)
|
141
|
+
end
|
142
|
+
RUBY
|
143
|
+
end
|
144
|
+
|
145
|
+
_decl_rels[rel_type.to_sym] = Neo4j::Wrapper::HasN::DeclRel.new(rel_type, true, self)
|
146
|
+
end
|
147
|
+
|
148
|
+
def define_has_n_methods_for(rel_type, options) #:nodoc:
|
149
|
+
unless method_defined?(rel_type)
|
150
|
+
class_eval <<-RUBY, __FILE__, __LINE__
|
151
|
+
def #{rel_type}
|
152
|
+
dsl = _decl_rels_for(:'#{rel_type}')
|
153
|
+
storage = _create_or_get_storage_for_decl_rels(dsl)
|
154
|
+
NodesDSL.new(storage, dsl.dir)
|
155
|
+
end
|
156
|
+
RUBY
|
157
|
+
end
|
158
|
+
|
159
|
+
unless method_defined?("#{rel_type}=".to_sym)
|
160
|
+
|
161
|
+
# TODO: This is a temporary fix for allowing running neo4j with Formtastic, issue 109
|
162
|
+
# A better solution might be to implement accept_ids for has_n relationship and
|
163
|
+
# make sure (somehow) that Formtastic uses the _ids methods.
|
164
|
+
|
165
|
+
class_eval <<-RUBY, __FILE__, __LINE__
|
166
|
+
def #{rel_type}=(nodes)
|
167
|
+
if nodes.is_a?(Array) && nodes.first.is_a?(String)
|
168
|
+
if nodes.first.blank?
|
169
|
+
self.#{rel_type}_rels.destroy_all
|
170
|
+
nodes.shift
|
171
|
+
end
|
172
|
+
else
|
173
|
+
self.#{rel_type}_rels.destroy_all
|
174
|
+
end
|
175
|
+
association = self.#{rel_type}
|
176
|
+
nodes.each { |node| association << node }
|
177
|
+
end
|
178
|
+
RUBY
|
179
|
+
end
|
180
|
+
|
181
|
+
unless method_defined?("#{rel_type}_rels".to_sym)
|
182
|
+
class_eval <<-RUBY, __FILE__, __LINE__
|
183
|
+
def #{rel_type}_rels
|
184
|
+
dsl = _decl_rels_for(:'#{rel_type}')
|
185
|
+
storage = _create_or_get_storage_for_decl_rels(dsl)
|
186
|
+
RelsDSL.new(storage, dsl.dir)
|
187
|
+
end
|
188
|
+
RUBY
|
189
|
+
end
|
190
|
+
|
191
|
+
instance_eval <<-RUBY, __FILE__, __LINE__
|
192
|
+
def #{rel_type}
|
193
|
+
_decl_rels[:'#{rel_type}'].rel_type.to_s
|
194
|
+
end
|
195
|
+
RUBY
|
196
|
+
|
197
|
+
_decl_rels[rel_type.to_sym] = Neo4j::Wrapper::HasN::DeclRel.new(rel_type, false, self)
|
198
|
+
end
|
199
|
+
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Neo4j
|
2
|
+
module Rails
|
3
|
+
module Identity
|
4
|
+
|
5
|
+
def id
|
6
|
+
_java_entity ? _java_entity.neo_id.to_s : nil
|
7
|
+
end
|
8
|
+
|
9
|
+
def neo_id
|
10
|
+
_java_entity ? _java_entity.neo_id : nil
|
11
|
+
end
|
12
|
+
|
13
|
+
def getId
|
14
|
+
new_record? ? nil : neo_id
|
15
|
+
end
|
16
|
+
|
17
|
+
def ==(other)
|
18
|
+
new? ? self.__id__ == other.__id__ : _java_entity == (other)
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
data/lib/neo4j/rails/model.rb
CHANGED
@@ -1,285 +1,108 @@
|
|
1
1
|
module Neo4j
|
2
2
|
module Rails
|
3
|
-
|
4
|
-
# Includes the Neo4j::NodeMixin and adds ActiveRecord/Model like behaviour.
|
3
|
+
# Makes Neo4j nodes and relationships behave like active record objects.
|
5
4
|
# That means for example that you don't have to care about transactions since they will be
|
6
|
-
# automatically be created when needed.
|
5
|
+
# automatically be created when needed. Validation, Callbacks etc. are also supported.
|
7
6
|
#
|
8
|
-
#
|
7
|
+
# @example Traverse
|
8
|
+
# class Person < Neo4j::Rails::Model
|
9
|
+
# end
|
9
10
|
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
# * Neo4j::Rails::Validations :: enable validations
|
16
|
-
# * Neo4j::Rails::Callbacks :: enable callbacks
|
17
|
-
# * Neo4j::Rails::Finders :: ActiveRecord style find
|
18
|
-
# * Neo4j::Rails::Relationships :: handles persisted and none persisted relationships.
|
19
|
-
# * Neo4j::Rails::Compositions :: see Neo4j::Rails::Compositions::ClassMethods, similar to http://api.rubyonrails.org/classes/ActiveRecord/Aggregations/ClassMethods.html
|
20
|
-
# * ActiveModel::Observing # enable observers, see Rails documentation.
|
21
|
-
# * ActiveModel::Translation - class mixin
|
11
|
+
# person = Person.find(...)
|
12
|
+
# person.outgoing(:foo) << Person.create
|
13
|
+
# person.save!
|
14
|
+
# person.outgoing(:foo).depth(:all)...
|
15
|
+
# person.outgoing(:friends).map{|f| f.outgoing(:knows).to_a}.flatten
|
22
16
|
#
|
23
|
-
#
|
24
|
-
# This class only expose a limited set of traversals.
|
25
|
-
# If you want to access the raw java node to do traversals use the _java_node.
|
17
|
+
# @example Declared Relationships: has_n and has_one
|
26
18
|
#
|
27
19
|
# class Person < Neo4j::Rails::Model
|
28
20
|
# end
|
29
21
|
#
|
30
|
-
#
|
31
|
-
#
|
22
|
+
# class Person
|
23
|
+
# has_n(:friends).to(Person)
|
24
|
+
# has_n(:employed_by)
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# Person.new.foo << other_node
|
28
|
+
# Person.friends.build(:name => 'kalle')
|
32
29
|
#
|
33
|
-
#
|
30
|
+
# @example Declared Properties and Index
|
34
31
|
#
|
35
|
-
#
|
36
|
-
#
|
37
|
-
#
|
32
|
+
# class Person < Neo4j::Rails::Model
|
33
|
+
# property :name
|
34
|
+
# property :age, :type => Fixnum, :index => :exact
|
35
|
+
# end
|
38
36
|
#
|
39
|
-
#
|
37
|
+
# Person.create(:name => 'kalle', :age => 42, :undeclared_prop => 3.14)
|
38
|
+
# Person.find_by_age(42)
|
40
39
|
#
|
41
|
-
#
|
42
|
-
#
|
43
|
-
#
|
40
|
+
# @example Callbacks
|
41
|
+
#
|
42
|
+
# class Person < Neo4j::Rails::Model
|
43
|
+
# before_save :do_something
|
44
|
+
# def do_something
|
45
|
+
# end
|
46
|
+
# end
|
47
|
+
#
|
48
|
+
# = Class Method Modules
|
49
|
+
# * {Neo4j::Rails::Persistence::ClassMethods} defines methods like: <tt>create</tt> and <tt>destroy_all</tt>
|
50
|
+
# * {Neo4j::Rails::Attributes::ClassMethods} defines the <tt>property</tt> and <tt>columns</tt> methods.
|
51
|
+
# * {Neo4j::Rails::NestedAttributes::ClassMethods} defines <tt>accepts_nested_attributes_for</tt>
|
52
|
+
# * {Neo4j::Rails::HasN::ClassMethods} defines <tt>has_n</tt> and <tt>has_one</tt>
|
53
|
+
# * {Neo4j::Rails::Finders::ClassMethods} defines <tt>find</tt>
|
54
|
+
# * {Neo4j::Rails::Compositions::ClassMethods} defines <tt>composed_of</tt> method
|
55
|
+
# * {Neo4j::Rails::AcceptId::ClassMethods} defines <tt>accepts_id_for</tt> method.
|
44
56
|
#
|
45
57
|
class Model
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
# Initialize a Node with a set of properties (or empty if nothing is passed)
|
50
|
-
def initialize(attributes = {})
|
51
|
-
@properties_before_type_cast=java.util.HashMap.new
|
52
|
-
reset_attributes
|
53
|
-
clear_relationships
|
54
|
-
self.attributes = attributes if attributes.is_a?(Hash)
|
55
|
-
yield self if block_given?
|
56
|
-
end
|
57
|
-
|
58
|
-
def id
|
59
|
-
neo_id.nil? ? nil : neo_id.to_s
|
60
|
-
end
|
61
|
-
|
62
|
-
def hash
|
63
|
-
persisted? ? _java_entity.neo_id.hash : super
|
64
|
-
end
|
65
|
-
|
66
|
-
def to_param
|
67
|
-
persisted? ? neo_id.to_s : nil
|
68
|
-
end
|
69
|
-
|
70
|
-
|
71
|
-
# Returns an Enumerable of all (primary) key attributes
|
72
|
-
# or nil if model.persisted? is false
|
73
|
-
def to_key
|
74
|
-
persisted? ? [id] : nil
|
75
|
-
end
|
76
|
-
|
77
|
-
def reject_if?(proc_or_symbol, attr)
|
78
|
-
return false if proc_or_symbol.nil?
|
79
|
-
if proc_or_symbol.is_a?(Symbol)
|
80
|
-
meth = method(proc_or_symbol)
|
81
|
-
meth.arity == 0 ? meth.call : meth.call(attr)
|
82
|
-
else
|
83
|
-
proc_or_symbol.call(attr)
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
def to_model
|
88
|
-
self
|
89
|
-
end
|
90
|
-
|
91
|
-
def ==(other)
|
92
|
-
new? ? self.__id__ == other.__id__ : @_java_node == (other)
|
93
|
-
end
|
94
|
-
|
95
|
-
def reachable_from_ref_node?
|
96
|
-
Neo4j::Algo.all_path(self.class.ref_node_for_class, self).outgoing(self.class).outgoing(:_all).count > 0
|
97
|
-
end
|
98
|
-
|
99
|
-
def attribute_missing(method_id, *args, &block)
|
100
|
-
method_name = method_id.method_name
|
101
|
-
if property?(method_name)
|
102
|
-
self[method_name]
|
103
|
-
else
|
104
|
-
super
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
##
|
109
|
-
# :method: outgoing
|
110
|
-
#
|
111
|
-
# Similar to Neo4j::Traversal#outgoing but returns depth one only outgoing relationship
|
112
|
-
# which may not all be persisted.
|
113
|
-
# For only traversing persisted outgoing relationship of any depth or more advanced traversals, use
|
114
|
-
# the wrapped Java node instead.
|
115
|
-
#
|
116
|
-
# ==== Examples
|
117
|
-
#
|
118
|
-
# person.outgoing(:friends) << other_person
|
119
|
-
# person.save!
|
120
|
-
#
|
121
|
-
# person.outgoing(:friends).map{|f| f.outgoing(:knows).to_a}.flatten
|
122
|
-
#
|
123
|
-
# ==== Examples
|
124
|
-
#
|
125
|
-
# Neo4j::Transaction.run do
|
126
|
-
# person._java_node.outgoing(:friends) << other_person
|
127
|
-
# end
|
128
|
-
#
|
129
|
-
# person._java_node.outgoing(:friends).outgoing(:knows).depth(4)
|
130
|
-
#
|
131
|
-
# Notice you can also declare outgoing relationships with the #has_n and #has_one class method.
|
132
|
-
#
|
133
|
-
# See Neo4j::Rails::Relationships#outgoing
|
134
|
-
# See Neo4j::Traversal#outgoing (when using it from the _java_node)
|
135
|
-
|
136
|
-
|
137
|
-
##
|
138
|
-
# :method: incoming
|
139
|
-
#
|
140
|
-
# Returns incoming relationship of depth one which may not all be persisted.
|
141
|
-
# See #outgoing
|
142
|
-
|
143
|
-
|
144
|
-
##
|
145
|
-
# :method: rels
|
146
|
-
#
|
147
|
-
# Returns both incoming and outgoing relationships which may not all be persisted.
|
148
|
-
# If you only want to find persisted relationships: @node._java_node.rels@
|
149
|
-
#
|
150
|
-
# See Neo4j::Rails::Relationships#rels
|
151
|
-
# See Neo4j::Rels#rels or Neo4j::Rels
|
152
|
-
#
|
153
|
-
|
154
|
-
##
|
155
|
-
# :method: []
|
156
|
-
#
|
157
|
-
# Returns a property of this node, which may or may not have been declared with the class property method.
|
158
|
-
# Similar to Neo4j::Property#[] but can return not persisted properties as well.
|
159
|
-
|
160
|
-
##
|
161
|
-
# :method: []=
|
162
|
-
#
|
163
|
-
# Sets any property on the node.
|
164
|
-
# Similar to Neo4j::Property#[]= but you must call the #save method to persist the property.
|
165
|
-
|
166
|
-
##
|
167
|
-
# :singleton-method: property
|
168
|
-
#
|
169
|
-
# See Neo4j::Rails::Mapping::Property::ClassMethods#property
|
170
|
-
|
171
|
-
##
|
172
|
-
# :singleton-method: has_one
|
173
|
-
#
|
174
|
-
# Generates a has_one methods which returns an object of type Neo4j::Rails::Relationships::NodesDSL
|
175
|
-
# and a has_one method postfixed @_rel@ which return a Neo4j::Rails::Relationships::RelsDSL
|
176
|
-
#
|
177
|
-
# See also Neo4j::Rails::Mapping::Property::ClassMethods#has_one
|
178
|
-
#
|
179
|
-
|
180
|
-
##
|
181
|
-
# :singleton-method: columns
|
182
|
-
#
|
183
|
-
# Returns all defined properties as an array
|
184
|
-
|
185
|
-
##
|
186
|
-
# :singleton-method: has_n
|
187
|
-
#
|
188
|
-
# Generates a has_n method which returns an object of type Neo4j::Rails::Relationships::NodesDSL
|
189
|
-
# and a has_n method postfixed @_rel@ which return a Neo4j::Rails::Relationships::RelsDSL
|
190
|
-
#
|
191
|
-
# See also Neo4j::Rails::Mapping::Property::ClassMethods#has_n
|
192
|
-
#
|
58
|
+
extend ActiveModel::Translation
|
193
59
|
|
60
|
+
include Neo4j::NodeMixin
|
61
|
+
include ActiveModel::Dirty # track changes to attributes
|
62
|
+
include ActiveModel::MassAssignmentSecurity # handle attribute hash assignment
|
63
|
+
include ActiveModel::Observing # enable observers
|
64
|
+
include Neo4j::Rails::Identity
|
65
|
+
include Neo4j::Rails::Persistence # handles how to save, create and update the model
|
66
|
+
include Neo4j::Rails::NodePersistence # handles how to save, create and update the model
|
67
|
+
include Neo4j::Rails::Attributes # handles how to save and retrieve attributes and override the property class method
|
68
|
+
include Neo4j::Rails::NestedAttributes
|
69
|
+
include Neo4j::Rails::HasN # allows some additional options on the #property class method
|
70
|
+
include Neo4j::Rails::Serialization # enable to_xml and to_json
|
71
|
+
include Neo4j::Rails::Validations # enable validations
|
72
|
+
include Neo4j::Rails::Callbacks # enable callbacks
|
73
|
+
include Neo4j::Rails::Timestamps # handle created_at, updated_at timestamp properties
|
74
|
+
include Neo4j::Rails::Finders # ActiveRecord style find
|
75
|
+
include Neo4j::Rails::Relationships # for none persisted relationships
|
76
|
+
include Neo4j::Rails::Compositions
|
77
|
+
include Neo4j::Rails::AcceptId
|
78
|
+
include Neo4j::Rails::Relationships
|
194
79
|
|
195
80
|
# --------------------------------------
|
196
81
|
# Public Class Methods
|
197
82
|
# --------------------------------------
|
198
83
|
class << self
|
199
|
-
# NodeMixin overwrites the #new class method but it saves it as orig_new
|
200
|
-
# Here, we just get it back to normal
|
201
|
-
alias :new :orig_new
|
202
|
-
|
203
|
-
def transaction(&block)
|
204
|
-
Neo4j::Rails::Transaction.run do |tx|
|
205
|
-
block.call(tx)
|
206
|
-
end
|
207
|
-
end
|
208
|
-
|
209
|
-
def entity_load(id)
|
210
|
-
Neo4j::Node.load(id)
|
211
|
-
end
|
212
84
|
|
213
85
|
##
|
214
86
|
# Determines whether to use Time.local (using :local) or Time.utc (using :utc) when pulling
|
215
87
|
# dates and times from the database. This is set to :local by default.
|
88
|
+
# @api public
|
216
89
|
def default_timezone
|
217
90
|
@default_timezone || :local
|
218
91
|
end
|
219
92
|
|
93
|
+
# @api public
|
220
94
|
def default_timezone=(zone)
|
221
95
|
@default_timezone = zone
|
222
96
|
end
|
223
97
|
|
224
|
-
def accepts_nested_attributes_for(*attr_names)
|
225
|
-
options = attr_names.pop if attr_names[-1].is_a?(Hash)
|
226
|
-
|
227
|
-
attr_names.each do |association_name|
|
228
|
-
# Do some validation that we have defined the relationships we want to nest
|
229
|
-
rel = self._decl_rels[association_name.to_sym]
|
230
|
-
raise "No relationship declared with has_n or has_one with type #{association_name}" unless rel
|
231
|
-
raise "Can't use accepts_nested_attributes_for(#{association_name}) since it has not defined which class it has a relationship to, use has_n(#{association_name}).to(MyOtherClass)" unless rel.target_class
|
232
|
-
|
233
|
-
if rel.has_one?
|
234
|
-
send(:define_method, "#{association_name}_attributes=") do |attributes|
|
235
|
-
update_nested_attributes(association_name.to_sym, attributes, options)
|
236
|
-
end
|
237
|
-
else
|
238
|
-
send(:define_method, "#{association_name}_attributes=") do |attributes|
|
239
|
-
if attributes.is_a?(Array)
|
240
|
-
attributes.each do |attr|
|
241
|
-
update_nested_attributes(association_name.to_sym, attr, options)
|
242
|
-
end
|
243
|
-
else
|
244
|
-
attributes.each_value do |attr|
|
245
|
-
update_nested_attributes(association_name.to_sym, attr, options)
|
246
|
-
end
|
247
|
-
end
|
248
|
-
end
|
249
|
-
end
|
250
|
-
|
251
|
-
end
|
252
|
-
end
|
253
|
-
|
254
|
-
# When multitenancy is used, node should be findable only from current ref node.
|
255
|
-
def findable?(entity)
|
256
|
-
entity.is_a? self and entity.reachable_from_ref_node?
|
257
|
-
end
|
258
|
-
|
259
98
|
# Set the i18n scope to overwrite ActiveModel.
|
260
99
|
#
|
261
100
|
# @return [ Symbol ] :neo4j
|
101
|
+
# @api public
|
262
102
|
def i18n_scope
|
263
103
|
:neo4j
|
264
104
|
end
|
265
105
|
end
|
266
106
|
end
|
267
|
-
|
268
|
-
Model.class_eval do
|
269
|
-
extend ActiveModel::Translation
|
270
|
-
|
271
|
-
include Persistence # handles how to save, create and update the model
|
272
|
-
include Attributes # handles how to save and retrieve attributes
|
273
|
-
include Mapping::Property # allows some additional options on the #property class method
|
274
|
-
include Serialization # enable to_xml and to_json
|
275
|
-
include Validations # enable validations
|
276
|
-
include Callbacks # enable callbacks
|
277
|
-
include Timestamps # handle created_at, updated_at timestamp properties
|
278
|
-
include ActiveModel::Observing # enable observers
|
279
|
-
include Finders # ActiveRecord style find
|
280
|
-
include Relationships # for none persisted relationships
|
281
|
-
include Compositions
|
282
|
-
include AcceptId
|
283
|
-
end
|
284
107
|
end
|
285
|
-
end
|
108
|
+
end
|