neo4j-wrapper 0.0.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.
Files changed (88) hide show
  1. data/Gemfile +10 -0
  2. data/README.rdoc +64 -0
  3. data/lib/db/active_tx_log +1 -0
  4. data/lib/db/index/lucene/node/Person_exact/_0.fdt +0 -0
  5. data/lib/db/index/lucene/node/Person_exact/_0.fdx +0 -0
  6. data/lib/db/index/lucene/node/Person_exact/_0.fnm +1 -0
  7. data/lib/db/index/lucene/node/Person_exact/_0.frq +0 -0
  8. data/lib/db/index/lucene/node/Person_exact/_0.nrm +1 -0
  9. data/lib/db/index/lucene/node/Person_exact/_0.prx +0 -0
  10. data/lib/db/index/lucene/node/Person_exact/_0.tii +0 -0
  11. data/lib/db/index/lucene/node/Person_exact/_0.tis +0 -0
  12. data/lib/db/index/lucene/node/Person_exact/_1.fdt +0 -0
  13. data/lib/db/index/lucene/node/Person_exact/_1.fdx +0 -0
  14. data/lib/db/index/lucene/node/Person_exact/_1.fnm +1 -0
  15. data/lib/db/index/lucene/node/Person_exact/_1.frq +0 -0
  16. data/lib/db/index/lucene/node/Person_exact/_1.nrm +1 -0
  17. data/lib/db/index/lucene/node/Person_exact/_1.prx +0 -0
  18. data/lib/db/index/lucene/node/Person_exact/_1.tii +0 -0
  19. data/lib/db/index/lucene/node/Person_exact/_1.tis +0 -0
  20. data/lib/db/index/lucene/node/Person_exact/_2.fdt +0 -0
  21. data/lib/db/index/lucene/node/Person_exact/_2.fdx +0 -0
  22. data/lib/db/index/lucene/node/Person_exact/_2.fnm +1 -0
  23. data/lib/db/index/lucene/node/Person_exact/_2.frq +0 -0
  24. data/lib/db/index/lucene/node/Person_exact/_2.nrm +1 -0
  25. data/lib/db/index/lucene/node/Person_exact/_2.prx +0 -0
  26. data/lib/db/index/lucene/node/Person_exact/_2.tii +0 -0
  27. data/lib/db/index/lucene/node/Person_exact/_2.tis +0 -0
  28. data/lib/db/index/lucene/node/Person_exact/segments.gen +0 -0
  29. data/lib/db/index/lucene/node/Person_exact/segments_3 +0 -0
  30. data/lib/db/index/lucene-store.db +0 -0
  31. data/lib/db/index/lucene.log.active +0 -0
  32. data/lib/db/index.db +0 -0
  33. data/lib/db/messages.log +826 -0
  34. data/lib/db/neostore +0 -0
  35. data/lib/db/neostore.id +0 -0
  36. data/lib/db/neostore.nodestore.db +0 -0
  37. data/lib/db/neostore.nodestore.db.id +0 -0
  38. data/lib/db/neostore.propertystore.db +0 -0
  39. data/lib/db/neostore.propertystore.db.arrays +0 -0
  40. data/lib/db/neostore.propertystore.db.arrays.id +0 -0
  41. data/lib/db/neostore.propertystore.db.id +0 -0
  42. data/lib/db/neostore.propertystore.db.index +0 -0
  43. data/lib/db/neostore.propertystore.db.index.id +0 -0
  44. data/lib/db/neostore.propertystore.db.index.keys +0 -0
  45. data/lib/db/neostore.propertystore.db.index.keys.id +0 -0
  46. data/lib/db/neostore.propertystore.db.strings +0 -0
  47. data/lib/db/neostore.propertystore.db.strings.id +0 -0
  48. data/lib/db/neostore.relationshipstore.db +0 -0
  49. data/lib/db/neostore.relationshipstore.db.id +0 -0
  50. data/lib/db/neostore.relationshiptypestore.db +0 -0
  51. data/lib/db/neostore.relationshiptypestore.db.id +0 -0
  52. data/lib/db/neostore.relationshiptypestore.db.names +0 -0
  53. data/lib/db/neostore.relationshiptypestore.db.names.id +0 -0
  54. data/lib/db/nioneo_logical.log.active +0 -0
  55. data/lib/db/tm_tx_log.1 +0 -0
  56. data/lib/example.rb +34 -0
  57. data/lib/neo4j/identity_map.rb +109 -0
  58. data/lib/neo4j/node_mixin.rb +74 -0
  59. data/lib/neo4j/relationship_mixin.rb +62 -0
  60. data/lib/neo4j/type_converters/type_converters.rb +333 -0
  61. data/lib/neo4j-wrapper/class_methods.rb +27 -0
  62. data/lib/neo4j-wrapper/find.rb +65 -0
  63. data/lib/neo4j-wrapper/has_n/class_methods.rb +131 -0
  64. data/lib/neo4j-wrapper/has_n/decl_rel.rb +261 -0
  65. data/lib/neo4j-wrapper/has_n/instance_methods.rb +12 -0
  66. data/lib/neo4j-wrapper/has_n/nodes.rb +83 -0
  67. data/lib/neo4j-wrapper/node_mixin/class_methods.rb +53 -0
  68. data/lib/neo4j-wrapper/node_mixin/delegates.rb +140 -0
  69. data/lib/neo4j-wrapper/node_mixin/initialize.rb +43 -0
  70. data/lib/neo4j-wrapper/properties/class_methods.rb +150 -0
  71. data/lib/neo4j-wrapper/relationship_mixin/class_methods.rb +30 -0
  72. data/lib/neo4j-wrapper/relationship_mixin/delegates.rb +110 -0
  73. data/lib/neo4j-wrapper/relationship_mixin/initialize.rb +35 -0
  74. data/lib/neo4j-wrapper/rule/class_methods.rb +204 -0
  75. data/lib/neo4j-wrapper/rule/event_listener.rb +66 -0
  76. data/lib/neo4j-wrapper/rule/functions/count.rb +45 -0
  77. data/lib/neo4j-wrapper/rule/functions/function.rb +76 -0
  78. data/lib/neo4j-wrapper/rule/functions/sum.rb +31 -0
  79. data/lib/neo4j-wrapper/rule/instance_methods.rb +16 -0
  80. data/lib/neo4j-wrapper/rule/neo4j_core_ext/traverser.rb +29 -0
  81. data/lib/neo4j-wrapper/rule/rule.rb +134 -0
  82. data/lib/neo4j-wrapper/rule/rule_node.rb +205 -0
  83. data/lib/neo4j-wrapper/version.rb +5 -0
  84. data/lib/neo4j-wrapper/wrapper.rb +38 -0
  85. data/lib/neo4j-wrapper.rb +35 -0
  86. data/lib/test.rb +61 -0
  87. data/neo4j-wrapper.gemspec +31 -0
  88. metadata +162 -0
@@ -0,0 +1,65 @@
1
+ module Neo4j
2
+ module Wrapper
3
+ module Find
4
+ Neo4j::Core::Index::ClassMethods.send(:alias_method, :_orig_find, :find)
5
+
6
+ # If the #ref_node_for_class returns an object implementing the method #_index_prefix it
7
+ # will use that as prefix, otherwise the empty string.
8
+ # @return [String] the prefix name of the index
9
+ def index_prefix
10
+ return "" unless Neo4j.running?
11
+ return "" unless respond_to?(:ref_node_for_class)
12
+ ref_node = ref_node_for_class.wrapper
13
+ prefix = ref_node.send(:index_prefix) if ref_node.respond_to?(:index_prefix)
14
+ prefix ? prefix + "_" : ""
15
+ end
16
+
17
+
18
+ # @return [String] the name of the index, with index prefix
19
+ def _index_name
20
+ to_s.gsub("::", '_')
21
+ end
22
+
23
+ # Fall back to the threadlocal ref node by default.
24
+ # You can set your own reference node using the #ref_node method
25
+ # @return [Neo4j::Node] returns the Neo4j.ref_node
26
+ def ref_node_for_class
27
+ Neo4j.ref_node
28
+ end
29
+
30
+ # Assigns the reference node for a class via a supplied block.
31
+ #
32
+ # @example of usage:
33
+ # class Person
34
+ # include Neo4j::NodeMixin
35
+ # ref_node { Neo4j.default_ref_node }
36
+ # end
37
+ #
38
+ def ref_node(&block)
39
+ singleton = class << self;
40
+ self;
41
+ end
42
+ singleton.send(:define_method, :ref_node_for_class) { block.call }
43
+ end
44
+
45
+ # Overrides the Neo4j::Core::Index::ClassMethods#find method to check
46
+ # if any of the query parameters needs to be converted, (e.g. DateTime to Fixnum)
47
+ #
48
+ # @example
49
+ # Person.find(:since => (1.year.ago .. Time.now))
50
+ # @see http://rdoc.info/github/andreasronge/neo4j-core/Neo4j/Core/Index/Indexer#find-instance_method Neo4j::Core::Index::ClassMethods#find
51
+ def find(*query_params)
52
+ query = query_params.first
53
+ if query.is_a?(Hash)
54
+ query.each_pair do |k, v|
55
+ converter = _converter(k)
56
+ value = v.is_a?(Range) ? Range.new(converter.to_java(v.begin), converter.to_java(v.end), v.exclude_end?) : converter.to_java(v)
57
+ query[k] = value
58
+ end
59
+ end
60
+ _orig_find(*query_params)
61
+ end
62
+
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,131 @@
1
+ module Neo4j
2
+ module Wrapper
3
+ module HasN
4
+ module ClassMethods
5
+
6
+ # @return [Hash] a hash of all relationship and its configuration defined by has_n and has_one
7
+ def _decl_rels
8
+ @_decl_rels ||= {}
9
+ end
10
+
11
+ # make sure the inherited classes inherit the <tt>_decl_rels</tt> hash
12
+ def inherited(klass)
13
+ copy = _decl_rels.clone
14
+ copy.each_pair{|k,v| copy[k] = v.inherit_new}
15
+ klass.instance_variable_set(:@_decl_rels, copy)
16
+ super
17
+ end
18
+
19
+
20
+ # Specifies a relationship between two node classes.
21
+ # Generates assignment and accessor methods for the given relationship.
22
+ # Both incoming and outgoing relationships can be declared, see {Neo4j::Wrapper::HasN::DeclRel}
23
+ #
24
+ # @example has_n(:files)
25
+ #
26
+ # class FolderNode
27
+ # include Ne4j::NodeMixin
28
+ # has_n(:files)
29
+ # end
30
+ #
31
+ # folder = FolderNode.new
32
+ # folder.files << Neo4j::Node.new << Neo4j::Node.new
33
+ # folder.files.inject {...}
34
+ #
35
+ # FolderNode.files #=> 'files' the name of the relationship
36
+ #
37
+ # @example has_n(x).to(...)
38
+ #
39
+ # # You can declare which class it has relationship to.
40
+ # # The generated relationships will be prefixed with the name of that class.
41
+ # class FolderNode
42
+ # include Ne4j::NodeMixin
43
+ # has_n(:files).to(File)
44
+ # end
45
+ #
46
+ # FolderNode.files #=> 'File#files' the name of the relationship
47
+ #
48
+ # @example has_n(x).from(class, has_n_name)
49
+ #
50
+ # # generate accessor method for traversing and adding relationship on incoming nodes.
51
+ # class FileNode
52
+ # include Ne4j::NodeMixin
53
+ # has_one(:folder).from(FolderNode, :files)
54
+ # end
55
+ #
56
+ #
57
+ # @return [Neo4j::Wrapper::HasN::DeclRel] a DSL object where the has_n relationship can be futher specified
58
+ def has_n(rel_type)
59
+ clazz = self
60
+ module_eval(%Q{
61
+ def #{rel_type}
62
+ dsl = _decl_rels_for('#{rel_type}'.to_sym)
63
+ Neo4j::Wrapper::HasN::Nodes.new(self, dsl)
64
+ end}, __FILE__, __LINE__)
65
+
66
+
67
+ module_eval(%Q{
68
+ def #{rel_type}_rels
69
+ dsl = _decl_rels_for('#{rel_type}'.to_sym)
70
+ dsl.all_relationships(self)
71
+ end}, __FILE__, __LINE__)
72
+
73
+ instance_eval(%Q{
74
+ def #{rel_type}
75
+ _decl_rels[:#{rel_type}].rel_type.to_s
76
+ end}, __FILE__, __LINE__)
77
+
78
+ _decl_rels[rel_type.to_sym] = DeclRel.new(rel_type, false, clazz)
79
+ end
80
+
81
+
82
+ # Specifies a relationship between two node classes.
83
+ # Generates assignment and accessor methods for the given relationship
84
+ # Old relationship is deleted when a new relationship is assigned.
85
+ # Both incoming and outgoing relationships can be declared, see {Neo4j::Wrapper::HasN::DeclRel}
86
+ #
87
+ # @example
88
+ #
89
+ # class FileNode
90
+ # include Ne4j::NodeMixin
91
+ # has_one(:folder)
92
+ # end
93
+ #
94
+ # file = FileNode.new
95
+ # file.folder = Neo4j::Node.new
96
+ # file.folder # => the node above
97
+ # file.folder_rel # => the relationship object between those nodes
98
+ #
99
+ # @return [Neo4j::Wrapper::HasN::DeclRel] a DSL object where the has_one relationship can be futher specified
100
+ def has_one(rel_type)
101
+ clazz = self
102
+ module_eval(%Q{def #{rel_type}=(value)
103
+ dsl = _decl_rels_for(:#{rel_type})
104
+ rel = dsl.single_relationship(self)
105
+ rel.del unless rel.nil?
106
+ dsl.create_relationship_to(self, value) if value
107
+ end}, __FILE__, __LINE__)
108
+
109
+ module_eval(%Q{def #{rel_type}
110
+ dsl = _decl_rels_for(:#{rel_type})
111
+ dsl.single_node(self)
112
+ end}, __FILE__, __LINE__)
113
+
114
+ module_eval(%Q{def #{rel_type}_rel
115
+ dsl = _decl_rels_for(:#{rel_type})
116
+ dsl.single_relationship(self)
117
+ end}, __FILE__, __LINE__)
118
+
119
+ instance_eval(%Q{
120
+ def #{rel_type}
121
+ _decl_rels[:#{rel_type}].rel_type.to_s
122
+ end}, __FILE__, __LINE__)
123
+
124
+ _decl_rels[rel_type.to_sym] = DeclRel.new(rel_type, true, clazz)
125
+ end
126
+
127
+ end
128
+ end
129
+ end
130
+
131
+ end
@@ -0,0 +1,261 @@
1
+ module Neo4j
2
+ module Wrapper
3
+ module HasN
4
+
5
+
6
+ # A DSL for declared relationships has_n and has_one
7
+ # This DSL will be used to create accessor methods for relationships.
8
+ # Instead of using the 'raw' Neo4j::NodeMixin#rels method where one needs to know
9
+ # the name of relationship and direction one can use the generated accessor methods.
10
+ #
11
+ # The DSL can also be used to specify a mapping to a Ruby class for a relationship, see Neo4j::HasN::DeclRelationshipDsl#relationship
12
+ #
13
+ # @example
14
+ #
15
+ # class Folder
16
+ # include Neo4j::NodeMixin
17
+ # property :name
18
+ # # Declaring a Many relationship to any other node
19
+ # has_n(:files)
20
+ # end
21
+ #
22
+ # class File
23
+ # include Neo4j::NodeMixin
24
+ # # declaring a incoming relationship from Folder's relationship files
25
+ # has_one(:folder).from(Folder, :files)
26
+ # end
27
+ #
28
+ # The following methods will be generated:
29
+ # <b>Folder#files</b> :: returns an Enumerable of outgoing nodes for relationship 'files'
30
+ # <b>Folder#files_rels</b> :: returns an Enumerable of outgoing relationships for relationship 'files'
31
+ # <b>File#folder</b> :: for adding one node for the relationship 'files' from the outgoing Folder node
32
+ # <b>File#folder_rel</b> :: for accessing relationship 'files' from the outgoing Folder node
33
+ # <b>File#folder</b> :: for accessing nodes from relationship 'files' from the outgoing Folder node
34
+ #
35
+ class DeclRel
36
+ attr_reader :target_class, :source_class, :dir, :rel_type
37
+
38
+ def initialize(method_id, has_one, target_class)
39
+ @method_id = method_id
40
+ @has_one = has_one
41
+ @target_class = target_class
42
+ @dir = :outgoing
43
+ @rel_type = method_id.to_s
44
+ @source_class = target_class
45
+ end
46
+
47
+ def inherit_new
48
+ base = self
49
+ dr = DeclRel.new(@method_id, @has_one, @target_class)
50
+ dr.instance_eval do
51
+ @dir = base.dir
52
+ @rel_type = base.rel_type
53
+ @source_class = base.source_class
54
+ end
55
+ dr
56
+ end
57
+
58
+ def to_s
59
+ "DeclRel #{object_id} dir: #{@dir} rel_id: #{@method_id}, rel_type: #{@rel_type}, target_class:#{@target_class} rel_class:#{@relationship}"
60
+ end
61
+
62
+ # @return [true, false]
63
+ def has_one?
64
+ @has_one
65
+ end
66
+
67
+ # @return [true, false]
68
+ def has_n?
69
+ !@has_one
70
+ end
71
+
72
+ # @return [true,false]
73
+ def incoming? #:nodoc:
74
+ @dir == :incoming
75
+ end
76
+
77
+
78
+ # Specifies an outgoing relationship.
79
+ # The name of the outgoing class will be used as a prefix for the relationship used.
80
+ #
81
+ # @example Example
82
+ # class FolderNode
83
+ # include Neo4j::NodeMixin
84
+ # has_n(:files).to(FileNode)
85
+ # end
86
+ #
87
+ # folder = FolderNode.new
88
+ # # generate a relationship between folder and file of type 'FileNode#files'
89
+ # folder.files << FileNode.new
90
+ #
91
+ # @example without prefix
92
+ #
93
+ # class FolderNode
94
+ # include Neo4j::NodeMixin
95
+ # has_n(:files).to(:contains)
96
+ # end
97
+ #
98
+ # file = FileNode.new
99
+ # # create an outgoing relationship of type 'contains' from folder node to file
100
+ # folder.files << FolderNode.new
101
+ #
102
+ # @param [Class] target the other class to which this relationship goes
103
+ # @return self
104
+ def to(target)
105
+ @dir = :outgoing
106
+
107
+ if Class === target
108
+ # handle e.g. has_n(:friends).to(class)
109
+ @target_class = target
110
+ @rel_type = "#{@source_class}##{@method_id}"
111
+ elsif Symbol === target
112
+ # handle e.g. has_n(:friends).to(:knows)
113
+ @rel_type = target.to_s
114
+ else
115
+ raise "Expected a class or a symbol for, got #{target}/#{target.class}"
116
+ end
117
+ self
118
+ end
119
+
120
+ # Specifies an incoming relationship.
121
+ # Will use the outgoing relationship given by the from class.
122
+ #
123
+ # @example with prefix FileNode
124
+ # class FolderNode
125
+ # include Neo4j::NodeMixin
126
+ # has_n(:files).to(FileNode)
127
+ # end
128
+ #
129
+ # class FileNode
130
+ # include Neo4j::NodeMixin
131
+ # # will only traverse any incoming relationship of type files from node FileNode
132
+ # has_one(:folder).from(FolderNode, :files)
133
+ # end
134
+ #
135
+ # file = FileNode.new
136
+ # # create an outgoing relationship of type 'FileNode#files' from folder node to file (FileNode is the prefix).
137
+ # file.folder = FolderNode.new
138
+ #
139
+ # @example without prefix
140
+ #
141
+ # class FolderNode
142
+ # include Neo4j::NodeMixin
143
+ # has_n(:files)
144
+ # end
145
+ #
146
+ # class FileNode
147
+ # include Neo4j::NodeMixin
148
+ # has_one(:folder).from(:files) # will traverse any incoming relationship of type files
149
+ # end
150
+ #
151
+ # file = FileNode.new
152
+ # # create an outgoing relationship of type 'files' from folder node to file
153
+ # file.folder = FolderNode.new
154
+ #
155
+ #
156
+ def from(*args)
157
+ @dir = :incoming
158
+
159
+ if args.size > 1
160
+ # handle specified (prefixed) relationship, e.g. has_n(:known_by).from(clazz, :type)
161
+ @target_class = args[0]
162
+ @rel_type = "#{@target_class}##{args[1]}"
163
+ @relationship_name = args[1].to_sym
164
+ elsif Symbol === args[0]
165
+ # handle unspecified (unprefixed) relationship, e.g. has_n(:known_by).from(:type)
166
+ @rel_type = args[0].to_s
167
+ else
168
+ raise "Expected a symbol for, got #{args[0]}"
169
+ end
170
+ self
171
+ end
172
+
173
+ # Specifies which relationship ruby class to use for the relationship
174
+ #
175
+ # @example
176
+ #
177
+ # class OrderLine
178
+ # include Neo4j::RelationshipMixin
179
+ # property :units
180
+ # property :unit_price
181
+ # end
182
+ #
183
+ # class Order
184
+ # property :total_cost
185
+ # property :dispatched
186
+ # has_n(:products).to(Product).relationship(OrderLine)
187
+ # end
188
+ #
189
+ # order = Order.new
190
+ # order.products << Product.new
191
+ # order.products_rels.first # => OrderLine
192
+ #
193
+ def relationship(rel_class)
194
+ @relationship = rel_class
195
+ self
196
+ end
197
+
198
+
199
+ # @private
200
+ def relationship_class # :nodoc:
201
+ if !@relationship_name.nil? && @relationship.nil?
202
+ other_class_dsl = @target_class._decl_rels[@relationship_name]
203
+ if other_class_dsl
204
+ @relationship = other_class_dsl.relationship_class
205
+ else
206
+ Neo4j.logger.warn "Unknown outgoing relationship #{@relationship_name} on #{@target_class}"
207
+ end
208
+ end
209
+ @relationship
210
+ end
211
+
212
+ # @private
213
+ def each_node(node, &block)
214
+ node.rels(dir, rel_type).each do |rel|
215
+ block.call(rel.other_node(node))
216
+ end
217
+ end
218
+
219
+ # @private
220
+ def _each_node(node, &block) #:nodoc:
221
+ node._rels(dir, rel_type).each do |rel|
222
+ block.call rel._other_node(node)
223
+ end
224
+ end
225
+
226
+ # @private
227
+ def single_node(node)
228
+ rel = single_relationship(node)
229
+ rel && rel.other_node(node)
230
+ end
231
+
232
+ # @private
233
+ def single_relationship(node) #:nodoc:
234
+ node.rel(dir, rel_type)
235
+ end
236
+
237
+ # @private
238
+ def _all_relationships(node) #:nodoc:
239
+ node._rels(dir, rel_type)
240
+ end
241
+
242
+ # @private
243
+ def all_relationships(node)
244
+ node.rels(dir, rel_type)
245
+ end
246
+
247
+ # @private
248
+ def create_relationship_to(node, other) # :nodoc:
249
+ from, to = incoming? ? [other, node] : [node, other]
250
+
251
+ if relationship_class
252
+ relationship_class.new(@rel_type, from._java_node, to._java_node)
253
+ else
254
+ Neo4j::Relationship.new(@rel_type, from, to)
255
+ end
256
+ end
257
+
258
+ end
259
+ end
260
+ end
261
+ end
@@ -0,0 +1,12 @@
1
+ module Neo4j
2
+ module Wrapper
3
+ module HasN
4
+ # The {Neo4j::Wrapper::HasN::ClassMethods} generates has_n relationship accessor methods.
5
+ module InstanceMethods
6
+ def _decl_rels_for(rel_type)
7
+ self.class._decl_rels[rel_type]
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,83 @@
1
+ module Neo4j
2
+ module Wrapper
3
+ module HasN
4
+
5
+ # The object created by a has_n or has_one Neo4j::NodeMixin class method which enables creating and traversal of nodes.
6
+ #
7
+ # @see Neo4j::Wrapper::HasN::ClassMethods
8
+ class Nodes
9
+ include Enumerable
10
+ include Neo4j::Core::ToJava
11
+
12
+ def initialize(node, decl_rel) # :nodoc:
13
+ @node = node
14
+ @decl_rel = decl_rel
15
+ end
16
+
17
+ def to_s
18
+ "HasN::Nodes [#{@decl_rel.dir}, id: #{@node.neo_id} type: #{@decl_rel && @decl_rel.rel_type} decl_rel:#{@decl_rel}]"
19
+ end
20
+
21
+ # Traverse the relationship till the index position
22
+ # @return [Neo4j::NodeMixin,Neo4j::Node,nil] the node at the given position
23
+ def [](index)
24
+ i = 0
25
+ each { |x| return x if i == index; i += 1 }
26
+ nil # out of index
27
+ end
28
+
29
+ # Pretend we are an array - this is necessarily for Rails actionpack/actionview/formhelper to work with this
30
+ def is_a?(type)
31
+ # ActionView requires this for nested attributes to work
32
+ return true if Array == type
33
+ super
34
+ end
35
+
36
+ # Required by the Enumerable mixin.
37
+ def each
38
+ @decl_rel.each_node(@node) { |n| yield n } # Should use yield here as passing &block through doesn't always work (why?)
39
+ end
40
+
41
+ # returns none wrapped nodes, you may get better performance using this method
42
+ def _each
43
+ @decl_rel._each_node(@node) { |n| yield n }
44
+ end
45
+
46
+ # Returns an real ruby array.
47
+ def to_ary
48
+ self.to_a
49
+ end
50
+
51
+ # Returns true if there are no node in this type of relationship
52
+ def empty?
53
+ first == nil
54
+ end
55
+
56
+
57
+ # Creates a relationship instance between this and the other node.
58
+ # Returns the relationship object
59
+ def new(other)
60
+ @decl_rel.create_relationship_to(@node, other)
61
+ end
62
+
63
+
64
+ # Creates a relationship between this and the other node.
65
+ #
66
+ # @example Person includes the Neo4j::NodeMixin and declares a has_n :friends
67
+ #
68
+ # p = Person.new # Node has declared having a friend type of relationship
69
+ # n1 = Node.new
70
+ # n2 = Node.new
71
+ #
72
+ # p.friends << n2 << n3
73
+ #
74
+ # @return self
75
+ def <<(other)
76
+ @decl_rel.create_relationship_to(@node, other)
77
+ self
78
+ end
79
+ end
80
+
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,53 @@
1
+ module Neo4j
2
+ module Wrapper
3
+ module NodeMixin
4
+ module ClassMethods
5
+
6
+ # Creates a new node or loads an already existing Neo4j node.
7
+ #
8
+ # You can use two callback method to initialize the node
9
+ # init_on_load - this method is called when the node is loaded from the database
10
+ # init_on_create - called when the node is created, will be provided with the same argument as the new method
11
+ #
12
+ # == Does
13
+ # * sets the neo4j property '_classname' to self.class.to_s
14
+ # * creates a neo4j node java object (in @_java_node)
15
+ #
16
+ # If you want to provide your own initialize method you should instead implement the
17
+ # method init_on_create method.
18
+ #
19
+ # @example Create your own Ruby wrapper around a Neo4j::Node java object
20
+ # class MyNode
21
+ # include Neo4j::NodeMixin
22
+ # end
23
+ #
24
+ # node = MyNode.new(:name => 'jimmy', :age => 23)
25
+ #
26
+ # @example Using your own initialize method
27
+ # class MyNode
28
+ # include Neo4j::NodeMixin
29
+ #
30
+ # def init_on_create(name, age)
31
+ # self[:name] = name
32
+ # self[:age] = age
33
+ # end
34
+ # end
35
+ #
36
+ # node = MyNode.new('jimmy', 23)
37
+ #
38
+ # @param args typically a hash of properties, but could be anything which will be handled in the super method
39
+ # @return the object return from the super method
40
+ def new(*args)
41
+ node = Neo4j::Node.create
42
+ wrapped_node = super()
43
+ Neo4j::IdentityMap.add(node, wrapped_node)
44
+ wrapped_node.init_on_load(node)
45
+ wrapped_node.init_on_create(*args)
46
+ wrapped_node
47
+ end
48
+
49
+ alias_method :create, :new
50
+ end
51
+ end
52
+ end
53
+ end