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
@@ -34,7 +34,7 @@ module Neo4j
|
|
34
34
|
class DeclRelationshipDsl
|
35
35
|
include Neo4j::ToJava
|
36
36
|
|
37
|
-
attr_reader :target_class, :dir, :rel_type
|
37
|
+
attr_reader :target_class, :source_class, :dir, :rel_type
|
38
38
|
|
39
39
|
def initialize(method_id, has_one, target_class)
|
40
40
|
@dir = :outgoing
|
@@ -42,6 +42,7 @@ module Neo4j
|
|
42
42
|
@has_one = has_one
|
43
43
|
@rel_type = method_id
|
44
44
|
@target_class = target_class
|
45
|
+
@source_class = target_class
|
45
46
|
end
|
46
47
|
|
47
48
|
def to_s
|
@@ -63,7 +64,7 @@ module Neo4j
|
|
63
64
|
def java_dir
|
64
65
|
dir_to_java(@dir)
|
65
66
|
end
|
66
|
-
|
67
|
+
|
67
68
|
def each_node(node, &block) #:nodoc:
|
68
69
|
node._java_node.getRelationships(java_rel_type, java_dir).each do |rel|
|
69
70
|
block.call(rel.getOtherNode(node).wrapper)
|
@@ -141,7 +142,7 @@ module Neo4j
|
|
141
142
|
if (Class === target)
|
142
143
|
# handle e.g. has_n(:friends).to(class)
|
143
144
|
@target_class = target
|
144
|
-
@rel_type = "#{@
|
145
|
+
@rel_type = "#{@source_class}##{@method_id}"
|
145
146
|
elsif (Symbol === target)
|
146
147
|
# handle e.g. has_n(:friends).to(:knows)
|
147
148
|
@rel_type = target.to_s
|
@@ -163,7 +164,7 @@ module Neo4j
|
|
163
164
|
# class FileNode
|
164
165
|
# include Neo4j::NodeMixin
|
165
166
|
# # will only traverse any incoming relationship of type files from node FileNode
|
166
|
-
# has_one(:folder).from(
|
167
|
+
# has_one(:folder).from(FolderNode, :files)
|
167
168
|
# end
|
168
169
|
#
|
169
170
|
# file = FileNode.new
|
@@ -183,7 +184,7 @@ module Neo4j
|
|
183
184
|
# end
|
184
185
|
#
|
185
186
|
# file = FileNode.new
|
186
|
-
# # create an outgoing relationship of type '
|
187
|
+
# # create an outgoing relationship of type 'files' from folder node to file
|
187
188
|
# file.folder = FolderNode.new
|
188
189
|
#
|
189
190
|
#
|
@@ -192,14 +193,9 @@ module Neo4j
|
|
192
193
|
|
193
194
|
if (args.size > 1)
|
194
195
|
# handle specified (prefixed) relationship, e.g. has_n(:known_by).from(clazz, :type)
|
195
|
-
@rel_type = "#{@target_class}##{args[1]}"
|
196
196
|
@target_class = args[0]
|
197
|
-
|
198
|
-
|
199
|
-
@relationship = other_class_dsl.relationship_class
|
200
|
-
else
|
201
|
-
Neo4j.logger.warn "Unknown outgoing relationship #{args[1]} on #{@target_class}"
|
202
|
-
end
|
197
|
+
@rel_type = "#{@target_class}##{args[1]}"
|
198
|
+
@relationship_name = args[1]
|
203
199
|
elsif (Symbol === args[0])
|
204
200
|
# handle unspecified (unprefixed) relationship, e.g. has_n(:known_by).from(:type)
|
205
201
|
@rel_type = args[0]
|
@@ -235,7 +231,15 @@ module Neo4j
|
|
235
231
|
end
|
236
232
|
|
237
233
|
def relationship_class # :nodoc:
|
238
|
-
@relationship
|
234
|
+
if !@relationship_name.nil? && @relationship.nil?
|
235
|
+
other_class_dsl = @target_class._decl_rels[@relationship_name]
|
236
|
+
if other_class_dsl
|
237
|
+
@relationship = other_class_dsl.relationship_class
|
238
|
+
else
|
239
|
+
Neo4j.logger.warn "Unknown outgoing relationship #{@relationship_name} on #{@target_class}"
|
240
|
+
end
|
241
|
+
end
|
242
|
+
@relationship
|
239
243
|
end
|
240
244
|
end
|
241
245
|
end
|
data/lib/neo4j/has_n/mapping.rb
CHANGED
@@ -7,7 +7,7 @@ module Neo4j
|
|
7
7
|
|
8
8
|
# The object created by a has_n or has_one Neo4j::NodeMixin class method which enables creating and traversal of nodes.
|
9
9
|
#
|
10
|
-
# Includes the Enumerable
|
10
|
+
# Includes the Enumerable mixin.
|
11
11
|
# The Neo4j::Mapping::ClassMethods::Relationship#has_n and Neo4j::Mapping::ClassMethods::Relationship#one
|
12
12
|
# methods returns an object of this type.
|
13
13
|
#
|
@@ -16,8 +16,6 @@ module Neo4j
|
|
16
16
|
#
|
17
17
|
class Mapping
|
18
18
|
include Enumerable
|
19
|
-
include WillPaginate::Finders::Base
|
20
|
-
|
21
19
|
include ToJava
|
22
20
|
|
23
21
|
def initialize(node, dsl) # :nodoc:
|
@@ -30,7 +28,7 @@ module Neo4j
|
|
30
28
|
end
|
31
29
|
|
32
30
|
def size
|
33
|
-
self.to_a.size
|
31
|
+
self.to_a.size # TODO: Optimise this
|
34
32
|
end
|
35
33
|
|
36
34
|
alias_method :length, :size
|
@@ -50,13 +48,13 @@ module Neo4j
|
|
50
48
|
end
|
51
49
|
|
52
50
|
# Required by the Enumerable mixin.
|
53
|
-
def each
|
54
|
-
@dsl.each_node(@node
|
51
|
+
def each
|
52
|
+
@dsl.each_node(@node) {|n| yield n} # Should use yield here as passing &block through doesn't always work (why?)
|
55
53
|
end
|
56
54
|
|
57
55
|
# returns none wrapped nodes, you may get better performance using this method
|
58
|
-
def _each
|
59
|
-
@dsl._each_node(@node
|
56
|
+
def _each
|
57
|
+
@dsl._each_node(@node) {|n| yield n}
|
60
58
|
end
|
61
59
|
|
62
60
|
# Returns an real ruby array.
|
@@ -64,21 +62,6 @@ module Neo4j
|
|
64
62
|
self.to_a
|
65
63
|
end
|
66
64
|
|
67
|
-
def wp_query(options, pager, args, &block) #:nodoc:
|
68
|
-
page = pager.current_page || 1
|
69
|
-
to = pager.per_page * page
|
70
|
-
from = to - pager.per_page
|
71
|
-
i = 0
|
72
|
-
res = []
|
73
|
-
_each do |node|
|
74
|
-
res << node.wrapper if i >= from
|
75
|
-
i += 1
|
76
|
-
break if i >= to
|
77
|
-
end
|
78
|
-
pager.replace res
|
79
|
-
pager.total_entries ||= self.size # TODO, this could be very slow to do
|
80
|
-
end
|
81
|
-
|
82
65
|
# Returns true if there are no node in this type of relationship
|
83
66
|
def empty?
|
84
67
|
first == nil
|
data/lib/neo4j/identity_map.rb
CHANGED
@@ -53,13 +53,19 @@ module Neo4j
|
|
53
53
|
#
|
54
54
|
# Person.index_names[:fulltext] => 'my_location'
|
55
55
|
# Person.index_names[:exact] => 'Foo_Person-exact' # default Location
|
56
|
-
#
|
57
|
-
#
|
56
|
+
#
|
57
|
+
# The index can be prefixed, see Neo4j#threadlocal_ref_node= and multi dendency.
|
58
58
|
#
|
59
59
|
# :singleton-method: index_names
|
60
60
|
|
61
61
|
|
62
|
-
|
62
|
+
##
|
63
|
+
# Returns a hash of which indexes has been defined and the type of index (:exact or :fulltext)
|
64
|
+
#
|
65
|
+
# :singleton-method: index_types
|
66
|
+
|
67
|
+
|
68
|
+
def_delegators :@_indexer, :index, :find, :index?, :index_type?, :delete_index_type, :rm_field_type, :add_index, :rm_index, :index_type_for, :index_names, :index_types
|
63
69
|
|
64
70
|
# Sets which indexer should be used for the given node class.
|
65
71
|
# You can share an indexer between several different classes.
|
data/lib/neo4j/index/index.rb
CHANGED
@@ -19,7 +19,8 @@ module Neo4j
|
|
19
19
|
# Neo4j::Index::ClassMethods::index
|
20
20
|
#
|
21
21
|
def add_index(field, value=self[field])
|
22
|
-
|
22
|
+
converted_value = Neo4j::TypeConverters.convert(value, field, self.class)
|
23
|
+
self.class.add_index(wrapped_entity, field.to_s, converted_value)
|
23
24
|
end
|
24
25
|
|
25
26
|
# Removes an index on the given property.
|
data/lib/neo4j/index/indexer.rb
CHANGED
@@ -2,6 +2,7 @@ module Neo4j
|
|
2
2
|
module Index
|
3
3
|
class Indexer
|
4
4
|
attr_reader :indexer_for, :field_types, :via_relationships, :entity_type, :parent_indexers, :via_relationships
|
5
|
+
alias_method :index_types, :field_types # public method accessible from node.index_types
|
5
6
|
|
6
7
|
def initialize(clazz, type) #:nodoc:
|
7
8
|
# part of the unique name of the index
|
@@ -155,7 +156,7 @@ module Neo4j
|
|
155
156
|
end
|
156
157
|
|
157
158
|
def update_single_index_on(node, field, old_val, new_val) #:nodoc:
|
158
|
-
if @field_types.
|
159
|
+
if @field_types.has_key?(field)
|
159
160
|
rm_index(node, field, old_val) if old_val
|
160
161
|
add_index(node, field, new_val) if new_val
|
161
162
|
end
|
@@ -322,7 +323,7 @@ module Neo4j
|
|
322
323
|
def index_names
|
323
324
|
@index_names ||= Hash.new do |hash, index_type|
|
324
325
|
default_filename = index_prefix + @indexer_for.to_s.gsub('::', '_')
|
325
|
-
hash.fetch(index_type) {"#{default_filename}
|
326
|
+
hash.fetch(index_type) {"#{default_filename}_#{index_type}"}
|
326
327
|
end
|
327
328
|
end
|
328
329
|
|
@@ -10,7 +10,7 @@ module Neo4j
|
|
10
10
|
def create_for(this_clazz, using_other_clazz, type)
|
11
11
|
@@indexers ||= {}
|
12
12
|
index = Indexer.new(this_clazz, type)
|
13
|
-
index.inherit_fields_from(@@indexers[using_other_clazz.to_s])
|
13
|
+
index.inherit_fields_from(@@indexers[using_other_clazz.to_s]) if @@indexers[using_other_clazz.to_s]
|
14
14
|
@@indexers[this_clazz.to_s] = index
|
15
15
|
end
|
16
16
|
|
@@ -37,8 +37,7 @@ module Neo4j
|
|
37
37
|
#
|
38
38
|
class LuceneQuery
|
39
39
|
include Enumerable
|
40
|
-
|
41
|
-
attr_accessor :left_and_query, :left_or_query
|
40
|
+
attr_accessor :left_and_query, :left_or_query, :right_not_query
|
42
41
|
|
43
42
|
def initialize(index, decl_props, query, params={})
|
44
43
|
@index = index
|
@@ -52,30 +51,9 @@ module Neo4j
|
|
52
51
|
end
|
53
52
|
end
|
54
53
|
|
55
|
-
|
56
|
-
@params[:page] = pager.current_page
|
57
|
-
@params[:per_page] = pager.per_page
|
58
|
-
pager.replace [*self]
|
59
|
-
pager.total_entries = size
|
60
|
-
end
|
61
|
-
|
62
|
-
# Since we include the Ruby Enumerable mixin we need this method.
|
54
|
+
# Implements the Ruby +Enumerable+ interface
|
63
55
|
def each
|
64
|
-
|
65
|
-
# paginate the result, used by the will_paginate gem
|
66
|
-
page = @params[:page] || 1
|
67
|
-
per_page = @params[:per_page]
|
68
|
-
to = per_page * page
|
69
|
-
from = to - per_page
|
70
|
-
i = 0
|
71
|
-
hits.each do |node|
|
72
|
-
yield node.wrapper if i >= from
|
73
|
-
i += 1
|
74
|
-
break if i >= to
|
75
|
-
end
|
76
|
-
else
|
77
|
-
hits.each { |n| yield n.wrapper }
|
78
|
-
end
|
56
|
+
hits.each { |x| yield x.wrapper }
|
79
57
|
end
|
80
58
|
|
81
59
|
# Close hits
|
@@ -156,9 +134,33 @@ module Neo4j
|
|
156
134
|
# Person.find(:name=>'kalle').and(:age => 3)
|
157
135
|
#
|
158
136
|
def and(query2)
|
159
|
-
|
160
|
-
|
161
|
-
|
137
|
+
LuceneQuery.new(@index, @decl_props, query2).tap { |new_query| new_query.left_and_query = self }
|
138
|
+
end
|
139
|
+
|
140
|
+
# Create an OR lucene query.
|
141
|
+
#
|
142
|
+
# ==== Parameters
|
143
|
+
# query2 :: the query that should be OR together
|
144
|
+
#
|
145
|
+
# ==== Example
|
146
|
+
#
|
147
|
+
# Person.find(:name=>'kalle').or(:age => 3)
|
148
|
+
#
|
149
|
+
def or(query2)
|
150
|
+
LuceneQuery.new(@index, @decl_props, query2).tap { |new_query| new_query.left_or_query = self }
|
151
|
+
end
|
152
|
+
|
153
|
+
# Create a NOT lucene query.
|
154
|
+
#
|
155
|
+
# ==== Parameters
|
156
|
+
# query2 :: the query that should exclude matching results
|
157
|
+
#
|
158
|
+
# ==== Example
|
159
|
+
#
|
160
|
+
# Person.find(:age => 3).not(:name=>'kalle')
|
161
|
+
#
|
162
|
+
def not(query2)
|
163
|
+
LuceneQuery.new(@index, @decl_props, query2).tap { |new_query| new_query.right_not_query = self }
|
162
164
|
end
|
163
165
|
|
164
166
|
|
@@ -175,11 +177,26 @@ module Neo4j
|
|
175
177
|
end
|
176
178
|
|
177
179
|
def build_and_query(query) #:nodoc:
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
180
|
+
build_composite_query(@left_and_query.build_query, query, org.apache.lucene.search.BooleanClause::Occur::MUST)
|
181
|
+
end
|
182
|
+
|
183
|
+
def build_or_query(query) #:nodoc:
|
184
|
+
build_composite_query(@left_or_query.build_query, query, org.apache.lucene.search.BooleanClause::Occur::SHOULD)
|
185
|
+
end
|
186
|
+
|
187
|
+
def build_not_query(query) #:nodoc:
|
188
|
+
right_query = @right_not_query.build_query
|
189
|
+
composite_query = org.apache.lucene.search.BooleanQuery.new
|
190
|
+
composite_query.add(query, org.apache.lucene.search.BooleanClause::Occur::MUST_NOT)
|
191
|
+
composite_query.add(right_query, org.apache.lucene.search.BooleanClause::Occur::MUST)
|
192
|
+
composite_query
|
193
|
+
end
|
194
|
+
|
195
|
+
def build_composite_query(left_query, right_query, opeartor) #:nodoc:
|
196
|
+
composite_query = org.apache.lucene.search.BooleanQuery.new
|
197
|
+
composite_query.add(left_query, opeartor)
|
198
|
+
composite_query.add(right_query, opeartor)
|
199
|
+
composite_query
|
183
200
|
end
|
184
201
|
|
185
202
|
def build_sort_query(query) #:nodoc:
|
@@ -224,6 +241,8 @@ module Neo4j
|
|
224
241
|
query = @query
|
225
242
|
query = build_hash_query(query) if Hash === query
|
226
243
|
query = build_and_query(query) if @left_and_query
|
244
|
+
query = build_or_query(query) if @left_or_query
|
245
|
+
query = build_not_query(query) if @right_not_query
|
227
246
|
query = build_sort_query(query) if @order
|
228
247
|
query
|
229
248
|
end
|
data/lib/neo4j/neo4j.rb
CHANGED
@@ -13,6 +13,9 @@ require 'neo4j/database'
|
|
13
13
|
#
|
14
14
|
module Neo4j
|
15
15
|
|
16
|
+
# The version of the Neo4j jar files
|
17
|
+
NEO_VERSION = Neo4j::Community::VERSION
|
18
|
+
|
16
19
|
class << self
|
17
20
|
# Start Neo4j using the default database.
|
18
21
|
# This is usally not required since the database will be started automatically when it is used.
|
@@ -71,6 +74,22 @@ module Neo4j
|
|
71
74
|
Neo4j::Config
|
72
75
|
end
|
73
76
|
|
77
|
+
# Executes a Cypher Query
|
78
|
+
# Check the neo4j http://docs.neo4j.org/chunked/milestone/cypher-query-lang.html
|
79
|
+
# Returns an enumerable of hash values.
|
80
|
+
#
|
81
|
+
# === Usage
|
82
|
+
#
|
83
|
+
# q = Neo4j.query("START n=node({node}) RETURN n", 'node' => @node.neo_id)
|
84
|
+
# q.first['n'] #=> the @node
|
85
|
+
# q.columns.first => 'n'
|
86
|
+
#
|
87
|
+
def query(query, params = {})
|
88
|
+
engine = org.neo4j.cypher.javacompat.ExecutionEngine.new(db)
|
89
|
+
engine.execute(query, params)
|
90
|
+
end
|
91
|
+
|
92
|
+
|
74
93
|
# Returns the logger used by neo4j.
|
75
94
|
# If not specified (with Neo4j.logger=) it will use the standard Ruby logger.
|
76
95
|
# You can change standard logger threshold by configuration :logger_level.
|
data/lib/neo4j/node.rb
CHANGED
@@ -7,42 +7,6 @@ require 'neo4j/equal'
|
|
7
7
|
require 'neo4j/load'
|
8
8
|
|
9
9
|
module Neo4j
|
10
|
-
|
11
|
-
org.neo4j.kernel.impl.core.NodeProxy.class_eval do
|
12
|
-
include Neo4j::Property
|
13
|
-
include Neo4j::Rels
|
14
|
-
include Neo4j::Traversal
|
15
|
-
include Neo4j::Equal
|
16
|
-
include Neo4j::Index
|
17
|
-
|
18
|
-
def del #:nodoc:
|
19
|
-
rels.each {|r| r.del}
|
20
|
-
delete
|
21
|
-
nil
|
22
|
-
end
|
23
|
-
|
24
|
-
def exist? #:nodoc:
|
25
|
-
Neo4j::Node.exist?(self)
|
26
|
-
end
|
27
|
-
|
28
|
-
def wrapped_entity #:nodoc:
|
29
|
-
self
|
30
|
-
end
|
31
|
-
|
32
|
-
def wrapper #:nodoc:
|
33
|
-
self.class.wrapper(self)
|
34
|
-
end
|
35
|
-
|
36
|
-
def _java_node #:nodoc:
|
37
|
-
self
|
38
|
-
end
|
39
|
-
|
40
|
-
def class #:nodoc:
|
41
|
-
Neo4j::Node
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
|
46
10
|
# A node in the graph with properties and relationships to other entities.
|
47
11
|
# Along with relationships, nodes are the core building blocks of the Neo4j data representation model.
|
48
12
|
# Node has three major groups of operations: operations that deal with relationships, operations that deal with properties and operations that traverse the node space.
|
@@ -259,6 +223,48 @@ module Neo4j
|
|
259
223
|
nil
|
260
224
|
end
|
261
225
|
|
226
|
+
def extend_java_class(java_clazz) #:nodoc:
|
227
|
+
java_clazz.class_eval do
|
228
|
+
include Neo4j::Property
|
229
|
+
include Neo4j::Rels
|
230
|
+
include Neo4j::Traversal
|
231
|
+
include Neo4j::Equal
|
232
|
+
include Neo4j::Index
|
233
|
+
|
234
|
+
def del #:nodoc:
|
235
|
+
rels.each { |r| r.del }
|
236
|
+
delete
|
237
|
+
nil
|
238
|
+
end
|
239
|
+
|
240
|
+
def exist? #:nodoc:
|
241
|
+
Neo4j::Node.exist?(self)
|
242
|
+
end
|
243
|
+
|
244
|
+
def wrapped_entity #:nodoc:
|
245
|
+
self
|
246
|
+
end
|
247
|
+
|
248
|
+
def wrapper #:nodoc:
|
249
|
+
self.class.wrapper(self)
|
250
|
+
end
|
251
|
+
|
252
|
+
def _java_node #:nodoc:
|
253
|
+
self
|
254
|
+
end
|
255
|
+
|
256
|
+
def class #:nodoc:
|
257
|
+
Neo4j::Node
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
262
261
|
end
|
263
262
|
end
|
263
|
+
|
264
|
+
# org.neo4j.kernel.HighlyAvailableGraphDatabase$LookupNode
|
265
|
+
#
|
266
|
+
Neo4j::Node.extend_java_class(org.neo4j.kernel.impl.core.NodeProxy)
|
267
|
+
|
268
|
+
|
269
|
+
|
264
270
|
end
|
@@ -36,8 +36,6 @@ module Neo4j
|
|
36
36
|
# * Neo4j::Index::ClassMethods
|
37
37
|
# * Neo4j::HasList::ClassMethods
|
38
38
|
#
|
39
|
-
# This class also includes the class mixin WillPaginate::Finders::Base, see http://github.com/mislav/will_paginate/wiki
|
40
|
-
#
|
41
39
|
module NodeMixin
|
42
40
|
include Neo4j::Index
|
43
41
|
|
@@ -80,7 +78,7 @@ module Neo4j
|
|
80
78
|
def _java_entity
|
81
79
|
@_java_node
|
82
80
|
end
|
83
|
-
|
81
|
+
|
84
82
|
# Trigger rules.
|
85
83
|
# You don't normally need to call this method (except in Migration) since
|
86
84
|
# it will be triggered automatically by the Neo4j::Rule::Rule
|
@@ -99,6 +97,13 @@ module Neo4j
|
|
99
97
|
self
|
100
98
|
end
|
101
99
|
|
100
|
+
def pagination_source(*a)
|
101
|
+
binding.pry
|
102
|
+
end
|
103
|
+
|
104
|
+
def self.pagination_source(*a)
|
105
|
+
binding.pry
|
106
|
+
end
|
102
107
|
|
103
108
|
def self.included(c) # :nodoc:
|
104
109
|
c.instance_eval do
|
@@ -119,7 +124,6 @@ module Neo4j
|
|
119
124
|
c.extend Neo4j::Rule::ClassMethods
|
120
125
|
c.extend Neo4j::HasList::ClassMethods
|
121
126
|
c.extend Neo4j::Index::ClassMethods
|
122
|
-
c.extend WillPaginate::Finders::Base
|
123
127
|
|
124
128
|
def c.inherited(subclass)
|
125
129
|
# inherit the index properties
|
@@ -131,7 +135,7 @@ module Neo4j
|
|
131
135
|
super
|
132
136
|
end
|
133
137
|
|
134
|
-
c.node_indexer c
|
138
|
+
c.node_indexer c unless c == Neo4j::Rails::Model
|
135
139
|
end
|
136
140
|
end
|
137
141
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Neo4j
|
2
|
+
|
3
|
+
# The class provides the pagination based on the given source.
|
4
|
+
# The source must be an Enumerable implementing methods drop, first and count (or size).
|
5
|
+
# This can be used to paginage any Enumerable collection and
|
6
|
+
# provides the integration point for other gems, like will_paginate and kaminari.
|
7
|
+
class Paginated
|
8
|
+
include Enumerable
|
9
|
+
attr_reader :items, :total, :current_page
|
10
|
+
|
11
|
+
def initialize(items, total, current_page)
|
12
|
+
@items, @total, @current_page = items, total, current_page
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.create_from(source, page, per_page)
|
16
|
+
partial = source.drop((page-1) * per_page).first(per_page)
|
17
|
+
Paginated.new(partial, source.count, page)
|
18
|
+
end
|
19
|
+
|
20
|
+
delegate :each, :to => :items
|
21
|
+
delegate :size, :[], :to => :items
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module Neo4j::Rails
|
2
|
+
# Allows accepting id for association objects. For example
|
3
|
+
# class Book < Neo4j::Model
|
4
|
+
# has_one(:author).to(Author)
|
5
|
+
# accepts_id_for :author
|
6
|
+
# end
|
7
|
+
#
|
8
|
+
# This would add a author_id getter and setter on Book. You could use
|
9
|
+
# book = Book.new(:name => 'Graph DBs', :author_id => 11)
|
10
|
+
# book.author_id # 11
|
11
|
+
# book.author_id = 13
|
12
|
+
# TODO: Support for has_n associations
|
13
|
+
module AcceptId
|
14
|
+
extend ActiveSupport::Concern
|
15
|
+
|
16
|
+
module ClassMethods
|
17
|
+
# Adds association_id getter and setter for one or more has_one associations
|
18
|
+
#
|
19
|
+
# @example
|
20
|
+
# class Book < Neo4j::Model
|
21
|
+
# has_one(:author).to(Author)
|
22
|
+
# has_one(:publisher).to(Publisher)
|
23
|
+
# accepts_id_for :author, :publisher
|
24
|
+
# end
|
25
|
+
def accepts_id_for(*association_names)
|
26
|
+
association_names.each do |association_name|
|
27
|
+
define_association_id_getter(association_name)
|
28
|
+
define_association_id_setter(association_name)
|
29
|
+
accepts_id_associations << association_name
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Check if model accepsts id for its association
|
34
|
+
# @example
|
35
|
+
# Book.accepts_id_for?(:author) => true
|
36
|
+
# Book.accepts_id_for?(:genre) => false
|
37
|
+
def accepts_id_for?(association_name)
|
38
|
+
accepts_id_associations.include?(association_name)
|
39
|
+
end
|
40
|
+
|
41
|
+
def accepts_id_associations #nodoc
|
42
|
+
@accepts_id_associations ||= []
|
43
|
+
end
|
44
|
+
|
45
|
+
protected
|
46
|
+
def define_association_id_getter(association_name)
|
47
|
+
class_eval %Q{
|
48
|
+
def #{association_name}_id
|
49
|
+
association_object = self.#{association_name}
|
50
|
+
association_object.present? ? association_object.id : nil
|
51
|
+
end
|
52
|
+
}, __FILE__, __LINE__
|
53
|
+
end
|
54
|
+
|
55
|
+
def define_association_id_setter(association_name)
|
56
|
+
class_eval %Q{
|
57
|
+
def #{association_name}_id=(id)
|
58
|
+
relation_target_class = self.class._decl_rels[:#{association_name}].target_class
|
59
|
+
association_class = relation_target_class <= self.class ? Neo4j::Model : relation_target_class
|
60
|
+
self.#{association_name} = id.present? ? association_class.find(id) : nil
|
61
|
+
end
|
62
|
+
}, __FILE__, __LINE__
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -38,7 +38,7 @@ module Neo4j
|
|
38
38
|
key_s = key.to_s
|
39
39
|
if !@properties.has_key?(key_s) || @properties[key_s] != value
|
40
40
|
attribute_will_change!(key_s)
|
41
|
-
@properties[key_s] = value
|
41
|
+
@properties[key_s] = value.nil? ? attribute_defaults[key_s] : value
|
42
42
|
end
|
43
43
|
value
|
44
44
|
end
|
@@ -98,16 +98,17 @@ module Neo4j
|
|
98
98
|
send(name + "=", nil)
|
99
99
|
else
|
100
100
|
|
101
|
-
|
101
|
+
#TODO: Consider extracting hardcoded assignments into "Binders"
|
102
|
+
value = if Neo4j::TypeConverters::TimeConverter.convert?(decl_type)
|
102
103
|
instantiate_time_object(name, values)
|
103
|
-
elsif
|
104
|
+
elsif Neo4j::TypeConverters::DateConverter.convert?(decl_type)
|
104
105
|
begin
|
105
106
|
values = values_with_empty_parameters.collect do |v| v.nil? ? 1 : v end
|
106
107
|
Date.new(*values)
|
107
108
|
rescue ArgumentError => ex # if Date.new raises an exception on an invalid date
|
108
109
|
instantiate_time_object(name, values).to_date # we instantiate Time object and convert it back to a date thus using Time's logic in handling invalid dates
|
109
110
|
end
|
110
|
-
elsif
|
111
|
+
elsif Neo4j::TypeConverters::DateTimeConverter.convert?(decl_type)
|
111
112
|
DateTime.new(*values)
|
112
113
|
else
|
113
114
|
raise "Unknown type #{decl_type}"
|
@@ -201,8 +202,8 @@ module Neo4j
|
|
201
202
|
# Known properties are either in the @properties, the declared
|
202
203
|
# properties or the property keys for the persisted node
|
203
204
|
def property?(name)
|
204
|
-
@properties.
|
205
|
-
self.class._decl_props.
|
205
|
+
@properties.has_key?(name) ||
|
206
|
+
self.class._decl_props.has_key?(name) ||
|
206
207
|
begin
|
207
208
|
persisted? && super
|
208
209
|
rescue org.neo4j.graphdb.NotFoundException
|
@@ -216,9 +217,13 @@ module Neo4j
|
|
216
217
|
def attribute?(name)
|
217
218
|
name[0] != ?_ && property?(name)
|
218
219
|
end
|
219
|
-
|
220
|
+
|
220
221
|
def _classname
|
221
|
-
self
|
222
|
+
self.class.to_s
|
223
|
+
end
|
224
|
+
|
225
|
+
def _classname=(value)
|
226
|
+
write_local_property_without_type_conversion("_classname",value)
|
222
227
|
end
|
223
228
|
|
224
229
|
# To get ActiveModel::Dirty to work, we need to be able to call undeclared
|
@@ -248,7 +253,7 @@ module Neo4j
|
|
248
253
|
|
249
254
|
# Wrap the setter in a conversion from Ruby to Java
|
250
255
|
def write_local_property_with_type_conversion(property, value)
|
251
|
-
|
256
|
+
@properties_before_type_cast[property.to_sym]=value if self.class._decl_props.has_key? property.to_sym
|
252
257
|
write_local_property_without_type_conversion(property, Neo4j::TypeConverters.to_java(self.class, property, value))
|
253
258
|
end
|
254
259
|
end
|