neo4j 1.0.0.beta.20 → 3.0.0.alpha.2

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 (79) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG +243 -0
  3. data/CONTRIBUTORS +12 -0
  4. data/Gemfile +10 -11
  5. data/README.md +23 -0
  6. data/bin/neo4j-jars +33 -0
  7. data/config/locales/en.yml +5 -0
  8. data/config/neo4j/config.yml +98 -0
  9. data/lib/neo4j.rb +28 -68
  10. data/lib/neo4j/active_node.rb +60 -0
  11. data/lib/neo4j/active_node/callbacks.rb +41 -0
  12. data/lib/neo4j/active_node/has_n.rb +138 -0
  13. data/lib/neo4j/active_node/has_n/decl_rel.rb +236 -0
  14. data/lib/neo4j/active_node/has_n/nodes.rb +82 -0
  15. data/lib/neo4j/active_node/identity.rb +28 -0
  16. data/lib/neo4j/active_node/initialize.rb +24 -0
  17. data/lib/neo4j/active_node/labels.rb +142 -0
  18. data/lib/neo4j/active_node/persistence.rb +193 -0
  19. data/lib/neo4j/active_node/property.rb +41 -0
  20. data/lib/neo4j/active_node/rels.rb +11 -0
  21. data/lib/neo4j/active_node/validations.rb +51 -0
  22. data/lib/neo4j/railtie.rb +40 -0
  23. data/lib/neo4j/version.rb +1 -1
  24. data/lib/neo4j/wrapper.rb +25 -0
  25. data/neo4j.gemspec +25 -15
  26. metadata +136 -149
  27. data/README.rdoc +0 -135
  28. data/lib/generators/neo4j.rb +0 -65
  29. data/lib/generators/neo4j/model/model_generator.rb +0 -39
  30. data/lib/generators/neo4j/model/templates/model.erb +0 -7
  31. data/lib/neo4j/config.rb +0 -153
  32. data/lib/neo4j/database.rb +0 -56
  33. data/lib/neo4j/equal.rb +0 -21
  34. data/lib/neo4j/event_handler.rb +0 -116
  35. data/lib/neo4j/index/class_methods.rb +0 -62
  36. data/lib/neo4j/index/index.rb +0 -33
  37. data/lib/neo4j/index/indexer.rb +0 -312
  38. data/lib/neo4j/index/indexer_registry.rb +0 -68
  39. data/lib/neo4j/index/lucene_query.rb +0 -191
  40. data/lib/neo4j/jars/geronimo-jta_1.1_spec-1.1.1.jar +0 -0
  41. data/lib/neo4j/jars/lucene-core-3.0.2.jar +0 -0
  42. data/lib/neo4j/jars/neo4j-index-1.2-1.2.M03.jar +0 -0
  43. data/lib/neo4j/jars/neo4j-kernel-1.2-1.2.M03.jar +0 -0
  44. data/lib/neo4j/jars/neo4j-lucene-index-0.2-1.2.M03.jar +0 -0
  45. data/lib/neo4j/load.rb +0 -21
  46. data/lib/neo4j/mapping/class_methods/init_node.rb +0 -50
  47. data/lib/neo4j/mapping/class_methods/init_rel.rb +0 -35
  48. data/lib/neo4j/mapping/class_methods/property.rb +0 -80
  49. data/lib/neo4j/mapping/class_methods/relationship.rb +0 -90
  50. data/lib/neo4j/mapping/class_methods/root.rb +0 -31
  51. data/lib/neo4j/mapping/class_methods/rule.rb +0 -295
  52. data/lib/neo4j/mapping/decl_relationship_dsl.rb +0 -214
  53. data/lib/neo4j/mapping/has_n.rb +0 -83
  54. data/lib/neo4j/mapping/node_mixin.rb +0 -97
  55. data/lib/neo4j/mapping/relationship_mixin.rb +0 -117
  56. data/lib/neo4j/model.rb +0 -4
  57. data/lib/neo4j/neo4j.rb +0 -95
  58. data/lib/neo4j/node.rb +0 -131
  59. data/lib/neo4j/node_mixin.rb +0 -4
  60. data/lib/neo4j/node_relationship.rb +0 -149
  61. data/lib/neo4j/node_traverser.rb +0 -157
  62. data/lib/neo4j/property.rb +0 -111
  63. data/lib/neo4j/rails/finders.rb +0 -121
  64. data/lib/neo4j/rails/lucene_connection_closer.rb +0 -19
  65. data/lib/neo4j/rails/mapping/property.rb +0 -35
  66. data/lib/neo4j/rails/model.rb +0 -324
  67. data/lib/neo4j/rails/railtie.rb +0 -16
  68. data/lib/neo4j/rails/transaction.rb +0 -67
  69. data/lib/neo4j/rails/tx_methods.rb +0 -15
  70. data/lib/neo4j/rails/validations/non_nil.rb +0 -11
  71. data/lib/neo4j/rails/validations/uniqueness.rb +0 -31
  72. data/lib/neo4j/rails/value.rb +0 -124
  73. data/lib/neo4j/rails/value_properties.rb +0 -29
  74. data/lib/neo4j/relationship.rb +0 -169
  75. data/lib/neo4j/relationship_mixin.rb +0 -4
  76. data/lib/neo4j/relationship_traverser.rb +0 -92
  77. data/lib/neo4j/to_java.rb +0 -31
  78. data/lib/neo4j/transaction.rb +0 -68
  79. data/lib/neo4j/type_converters.rb +0 -98
@@ -1,90 +0,0 @@
1
- module Neo4j::Mapping
2
- module ClassMethods
3
-
4
- module Relationship
5
- include Neo4j::ToJava
6
-
7
- # Specifies a relationship between two node classes.
8
- # Generates assignment and accessor methods for the given relationship.
9
- # Both incoming and outgoing relationships can be declared, see Neo4j::Mapping::DeclRelationshipDsl
10
- #
11
- # ==== Example
12
- #
13
- # class FolderNode
14
- # include Ne4j::NodeMixin
15
- # has_n(:files)
16
- # end
17
- #
18
- # folder = FolderNode.new
19
- # folder.files << Neo4j::Node.new << Neo4j::Node.new
20
- # folder.files.inject {...}
21
- #
22
- # ==== Returns
23
- #
24
- # Neo4j::Mapping::DeclRelationshipDsl
25
- #
26
- def has_n(rel_type, params = {})
27
- clazz = self
28
- module_eval(%Q{
29
- def #{rel_type}
30
- dsl = #{clazz}._decl_rels[:'#{rel_type.to_s}']
31
- Neo4j::Mapping::HasN.new(self, dsl)
32
- end}, __FILE__, __LINE__)
33
-
34
- module_eval(%Q{
35
- def #{rel_type}_rels
36
- dsl = #{clazz}._decl_rels[:'#{rel_type.to_s}']
37
- dsl.all_relationships(self)
38
- end}, __FILE__, __LINE__)
39
-
40
- _decl_rels[rel_type.to_sym] = Neo4j::Mapping::DeclRelationshipDsl.new(rel_type, false, clazz, params)
41
- end
42
-
43
-
44
- # Specifies a relationship between two node classes.
45
- # Generates assignment and accessor methods for the given relationship
46
- # Old relationship is deleted when a new relationship is assigned.
47
- # Both incoming and outgoing relationships can be declared, see Neo4j::Mapping::DeclRelationshipDsl
48
- #
49
- # ==== Example
50
- #
51
- # class FileNode
52
- # include Ne4j::NodeMixin
53
- # has_one(:folder)
54
- # end
55
- #
56
- # file = FileNode.new
57
- # file.folder = Neo4j::Node.new
58
- # file.folder # => the node above
59
- # file.folder_rel # => the relationship object between those nodes
60
- #
61
- # ==== Returns
62
- #
63
- # Neo4j::Mapping::DeclRelationshipDsl
64
- #
65
- def has_one(rel_type, params = {})
66
- clazz = self
67
- module_eval(%Q{def #{rel_type}=(value)
68
- dsl = #{clazz}._decl_rels[:'#{rel_type.to_s}']
69
- rel = dsl.single_relationship(self)
70
- rel.del unless rel.nil?
71
- dsl.create_relationship_to(self, value) if value
72
- end}, __FILE__, __LINE__)
73
-
74
- module_eval(%Q{def #{rel_type}
75
- dsl = #{clazz}._decl_rels[:'#{rel_type.to_s}']
76
- dsl.single_node(self)
77
- end}, __FILE__, __LINE__)
78
-
79
- module_eval(%Q{
80
- def #{rel_type}_rel
81
- dsl = #{clazz}._decl_rels[:'#{rel_type.to_s}']
82
- dsl.single_relationship(self)
83
- end}, __FILE__, __LINE__)
84
-
85
- _decl_rels[rel_type.to_sym] = Neo4j::Mapping::DeclRelationshipDsl.new(rel_type, true, clazz, params)
86
- end
87
-
88
- end
89
- end
90
- end
@@ -1,31 +0,0 @@
1
- module Neo4j::Mapping
2
- module ClassMethods
3
- # Used to hold information about which relationships and properties has been declared.
4
- module Root
5
- #attr_reader :_decl_rels, :_decl_props
6
-
7
- def root_class(clazz)
8
- @@_all_decl_rels ||= {}
9
- @@_all_decl_props ||= {}
10
- @@_all_decl_rels[clazz] ||= {}
11
- @@_all_decl_props[clazz] ||= {}
12
- @_decl_rels = @@_all_decl_rels[clazz]
13
- @_decl_props = @@_all_decl_props[clazz]
14
- end
15
-
16
-
17
- # a hash of all relationships which has been declared with a has_n or has_one using Neo4j::Mapping::ClassMethods::Relationship
18
- def _decl_rels
19
- @@_all_decl_rels[self] ||= {}
20
- @_decl_props = @@_all_decl_rels[self]
21
- end
22
-
23
- # a hash of all properties which has been declared with <tt>property</tt> using the Neo4j::Mapping::ClassMethods::Property
24
- def _decl_props
25
- @@_all_decl_props[self] ||= {}
26
- @_decl_props = @@_all_decl_props[self]
27
- end
28
-
29
- end
30
- end
31
- end
@@ -1,295 +0,0 @@
1
- module Neo4j::Mapping
2
- module ClassMethods
3
- # Holds all defined rules and trigger them when an event is received.
4
- #
5
- # See Rule
6
- #
7
- class Rules
8
- class << self
9
- def add(clazz, field, props, &block)
10
- clazz = clazz.to_s
11
- @rules ||= {}
12
- # was there no ruls for this class AND is neo4j running ?
13
- if !@rules.include?(clazz) && Neo4j.running?
14
- # maybe Neo4j was started first and the rules was added later. Create rule nodes now
15
- create_rule_node_for(clazz)
16
- end
17
- @rules[clazz] ||= {}
18
- filter = block.nil? ? Proc.new { |*| true } : block
19
- @rules[clazz][field] = filter
20
- @triggers ||= {}
21
- @triggers[clazz] ||= {}
22
- trigger = props[:trigger].nil? ? [] : props[:trigger]
23
- @triggers[clazz][field] = trigger.respond_to?(:each) ? trigger : [trigger]
24
- end
25
-
26
- def inherit(parent_class, subclass)
27
- # copy all the rules
28
- @rules[parent_class.to_s].each_pair do |field, filter|
29
- subclass.rule field, &filter
30
- end if @rules[parent_class.to_s]
31
- end
32
-
33
- def trigger_other_rules(node)
34
- clazz = node[:_classname]
35
- @rules[clazz].keys.each do |field|
36
- rel_types = @triggers[clazz][field]
37
- rel_types.each do |rel_type|
38
- node.incoming(rel_type).each { |n| n.trigger_rules }
39
- end
40
- end
41
- end
42
-
43
- def fields_for(clazz)
44
- clazz = clazz.to_s
45
- return [] if @rules.nil? || @rules[clazz].nil?
46
- @rules[clazz].keys
47
- end
48
-
49
- def delete(clazz)
50
- clazz = clazz.to_s
51
- # delete the rule node if found
52
- if Neo4j.ref_node.rel?(clazz)
53
- Neo4j.ref_node.outgoing(clazz).each { |n| n.del }
54
- end
55
- @rules.delete(clazz) if @rules
56
- end
57
-
58
- def on_neo4j_started(*)
59
- @rules.each_key { |clazz| create_rule_node_for(clazz) } if @rules
60
- end
61
-
62
- def create_rule_node_for(clazz)
63
- if !Neo4j.ref_node.rel?(clazz)
64
- Neo4j::Transaction.run do
65
- node = Neo4j::Node.new
66
- Neo4j.ref_node.outgoing(clazz) << node
67
- node
68
- end
69
- end
70
- end
71
-
72
- def trigger?(node)
73
- @rules && node.property?(:_classname) && @rules.include?(node[:_classname])
74
- end
75
-
76
- def rule_for(clazz)
77
- if Neo4j.ref_node.rel?(clazz)
78
- Neo4j.ref_node._rel(:outgoing, clazz)._end_node
79
- else
80
- # this should be called if the rule node gets deleted
81
- create_rule_node_for(clazz)
82
- end
83
- end
84
-
85
-
86
- def on_relationship_created(rel, *)
87
- trigger_start_node = trigger?(rel._start_node)
88
- trigger_end_node = trigger?(rel._end_node)
89
- # end or start node must be triggered by this event
90
- return unless trigger_start_node || trigger_end_node
91
- on_property_changed(trigger_start_node ? rel._start_node : rel._end_node)
92
- end
93
-
94
-
95
- def on_property_changed(node, *)
96
- trigger_rules(node) if trigger?(node)
97
- end
98
-
99
- def trigger_rules(node)
100
- trigger_rules_for_class(node, node[:_classname])
101
- trigger_other_rules(node)
102
- end
103
-
104
- def trigger_rules_for_class(node, clazz)
105
- return if @rules[clazz].nil?
106
-
107
- agg_node = rule_for(clazz)
108
- @rules[clazz].each_pair do |field, rule|
109
- if run_rule(rule, node)
110
- # is this node already included ?
111
- unless connected?(field, agg_node, node)
112
- agg_node.outgoing(field) << node
113
- end
114
- else
115
- # remove old ?
116
- break_connection(field, agg_node, node)
117
- end
118
- end
119
-
120
- # recursively add relationships for all the parent classes with rules that also pass for this node
121
- if clazz = eval("#{clazz}.superclass")
122
- trigger_rules_for_class(node, clazz.to_s)
123
- end
124
- end
125
-
126
- # work out if two nodes are connected by a particular relationship
127
- # uses the end_node to start with because it's more likely to have less relationships to go through
128
- # (just the number of superclasses it has really)
129
- def connected?(relationship, start_node, end_node)
130
- end_node.incoming(relationship).each do |n|
131
- return true if n == start_node
132
- end
133
- false
134
- end
135
-
136
- # sever a direct one-to-one relationship if it exists
137
- def break_connection(relationship, start_node, end_node)
138
- end_node.rels(relationship).incoming.each do |r|
139
- return r.del if r.start_node == start_node
140
- end
141
- end
142
-
143
- def run_rule(rule, node)
144
- if rule.arity != 1
145
- node.wrapper.instance_eval(&rule)
146
- else
147
- rule.call(node)
148
- end
149
- end
150
- end
151
- end
152
-
153
-
154
- # Allows you to group nodes by providing a rule.
155
- #
156
- # === Example, finding all nodes of a certain class
157
- # Just add a rule without a code block, then all nodes of that class will be grouped under the given key (<tt>all</tt>
158
- # for the example below).
159
- #
160
- # class Person
161
- # include Neo4j::NodeMixin
162
- # rule :all
163
- # end
164
- #
165
- # Then you can get all the nodes of type Person (and siblings) by
166
- # Person.all.each {|x| ...}
167
- #
168
- # === Example, finding all nodes with a given condition on a property
169
- #
170
- # class Person
171
- # include Neo4j::NodeMixin
172
- # property :age
173
- # rule(:old) { age > 10 }
174
- # end
175
- #
176
- # Now we can find all nodes with a property <tt>age</tt> above 10.
177
- #
178
- # === Chain Rules
179
- #
180
- # class NewsStory
181
- # include Neo4j::NodeMixin
182
- # has_n :readers
183
- # rule(:featured) { |node| node[:featured] == true }
184
- # rule(:young_readers) { !readers.find{|user| !user.young?}}
185
- # end
186
- #
187
- # You can combine two rules. Let say you want to find all stories which are featured and has young readers:
188
- # NewsStory.featured.young_readers.each {...}
189
- #
190
- # === Trigger Other Rules
191
- # You can let one rule trigger another rule.
192
- # Let say you have readers of some magazine and want to know if the magazine has old or young readers.
193
- # So when a reader change from young to old you want to trigger all the magazine that he reads (a but stupid example)
194
- #
195
- # Example
196
- # class Reader
197
- # include Neo4j::NodeMixin
198
- # property :age
199
- # rule(:young, :trigger => :readers) { age < 15 }
200
- # end
201
- #
202
- # class NewsStory
203
- # include Neo4j::NodeMixin
204
- # has_n :readers
205
- # rule(:young_readers) { !readers.find{|user| !user.young?}}
206
- # end
207
- #
208
- # === Performance Considerations
209
- # If you have many rules and many updates this can be a bit slow.
210
- # In order to speed it up somewhat you can use the raw java node object instead by providing an argument in your block.
211
- #
212
- # Example:
213
- #
214
- # class Person
215
- # include Neo4j::NodeMixin
216
- # property :age
217
- # rule(:old) {|node| node[:age] > 10 }
218
- # end
219
- #
220
- # === Thread Safe ?
221
- # Not sure...
222
- #
223
- module Rule
224
-
225
- # Creates an rule node attached to the Neo4j.ref_node
226
- # Can be used to rule all instances of a specific Ruby class.
227
- #
228
- # Example of usage:
229
- # class Person
230
- # include Neo4j
231
- # rule :all
232
- # rule :young { self[:age] < 10 }
233
- # end
234
- #
235
- # p1 = Person.new :age => 5
236
- # p2 = Person.new :age => 7
237
- # p3 = Person.new :age => 12
238
- # Neo4j::Transaction.finish
239
- # Person.all # => [p1,p2,p3]
240
- # Person.young # => [p1,p2]
241
- # p1.young? # => true
242
- #
243
- def rule(name, props = {}, &block)
244
- singelton = class << self;
245
- self;
246
- end
247
-
248
- # define class methods
249
- singelton.send(:define_method, name) do
250
- agg_node = Rules.rule_for(self)
251
- raise "no rule node for #{name} on #{self}" if agg_node.nil?
252
- traversal = agg_node.outgoing(name) # TODO possible to cache this object
253
- Rules.fields_for(self).each do |filter_name|
254
- traversal.filter_method(filter_name) do |path|
255
- path.end_node.rel?(filter_name, :incoming)
256
- end
257
- end
258
- traversal
259
- end unless respond_to?(name)
260
-
261
- # define instance methods
262
- self.send(:define_method, "#{name}?") do
263
- instance_eval &block
264
- end
265
-
266
- Rules.add(self, name, props, &block)
267
- end
268
-
269
- def inherit_rules_from(clazz)
270
- Rules.inherit(clazz, self)
271
- end
272
-
273
- # This is typically used for RSpecs to clean up rule nodes created by the #rule method.
274
- # It also remove the given class method.
275
- def delete_rules
276
- singelton = class << self;
277
- self;
278
- end
279
- Rules.fields_for(self).each do |name|
280
- singelton.send(:remove_method, name)
281
- end
282
- Rules.delete(self)
283
- end
284
-
285
- # Force to trigger the rules.
286
- # You don't normally need that since it will be done automatically.
287
- def trigger_rules(node)
288
- Rules.trigger_rules(node)
289
- end
290
-
291
- end
292
-
293
- Neo4j.unstarted_db.event_handler.add(Rules)
294
- end
295
- end
@@ -1,214 +0,0 @@
1
- module Neo4j::Mapping
2
-
3
-
4
- # A DSL for declared relationships has_n and has_one
5
- # This DSL will be used to create accessor methods for relationships.
6
- # Instead of using the 'raw' Neo4j::NodeMixin#rels method where one needs to know
7
- # the name of relationship and direction one can use the generated accessor methods.
8
- #
9
- # The DSL can also be used to specify a mapping to a Ruby class for a relationship, see Neo4j::Relationships::DeclRelationshipDsl#relationship
10
- #
11
- # ==== Example
12
- #
13
- # class Folder
14
- # include Neo4j::NodeMixin
15
- # property :name
16
- # # Declaring a Many relationship to any other node
17
- # has_n(:files)
18
- # end
19
- #
20
- # class File
21
- # include Neo4j::NodeMixin
22
- # # declaring a incoming relationship from Folder's relationship files
23
- # has_one(:folder).from(Folder, :files)
24
- # end
25
- #
26
- # The following methods will be generated:
27
- # <b>Folder#files</b> :: returns an Enumerable of outgoing nodes for relationship 'files'
28
- # <b>Folder#files_rels</b> :: returns an Enumerable of outgoing relationships for relationship 'files'
29
- # <b>File#folder</b> :: for adding one node for the relationship 'files' from the outgoing Folder node
30
- # <b>File#folder_rel</b> :: for accessing relationship 'files' from the outgoing Folder node
31
- # <b>File#folder</b> :: for accessing nodes from relationship 'files' from the outgoing Folder node
32
- #
33
- class DeclRelationshipDsl
34
- include Neo4j::ToJava
35
-
36
- attr_reader :target_class, :direction, :rel_type
37
-
38
- def initialize(method_id, has_one, target_class, params)
39
- @direction = :outgoing
40
- @method_id = method_id
41
- @has_one = has_one
42
- @rel_type = method_id
43
- @target_class = target_class
44
- end
45
-
46
- def to_s
47
- "DeclRelationshipDsl #{object_id} dir: #{@direction} rel_id: #{@method_id}, rel_type: #{@rel_type}, target_class:#{@target_class} rel_class:#{@relationship}"
48
- end
49
-
50
- def has_one?
51
- @has_one
52
- end
53
-
54
- def each_node(node, direction, &block) #:nodoc:
55
- type = type_to_java(rel_type)
56
- dir = dir_to_java(direction)
57
- node._java_node.getRelationships(type, dir).each do |rel|
58
- other = rel.getOtherNode(node).wrapper
59
- block.call other
60
- end
61
- end
62
-
63
- def incoming? #:nodoc:
64
- @direction == :incoming
65
- end
66
-
67
- def single_node(node) #:nodoc:
68
- rel = single_relationship(node)
69
- rel && rel.other_node(node).wrapper
70
- end
71
-
72
- def single_relationship(node) #:nodoc:
73
- node._java_node.rel(direction, rel_type)
74
- end
75
-
76
- def _all_relationships(node) #:nodoc:
77
- type = type_to_java(rel_type)
78
- dir = dir_to_java(direction)
79
- node._java_node.getRelationships(type, dir)
80
- end
81
-
82
- def all_relationships(node) #:nodoc:
83
- Neo4j::RelationshipTraverser.new(node._java_node, [rel_type], direction)
84
- end
85
-
86
- def create_relationship_to(node, other) # :nodoc:
87
- from, to = incoming? ? [other, node] : [node, other]
88
- java_type = type_to_java(rel_type)
89
-
90
- rel = from._java_node.create_relationship_to(to._java_node, java_type)
91
- rel[:_classname] = relationship_class.to_s if relationship_class
92
- rel.wrapper
93
- end
94
-
95
- # Specifies an outgoing relationship.
96
- # The name of the outgoing class will be used as a prefix for the relationship used.
97
- #
98
- # ==== Arguments
99
- # clazz:: to which class this relationship goes
100
- # relationship:: optional, the relationship to use
101
- #
102
- # ==== Example
103
- # class FolderNode
104
- # include Neo4j::NodeMixin
105
- # has_n(:files).to(FileNode)
106
- # end
107
- #
108
- # folder = FolderNode.new
109
- # # generate a relationship between folder and file of type 'FileNode#files'
110
- # folder.files << FileNode.new
111
- #
112
- def to(*args)
113
- @direction = :outgoing
114
-
115
- if (args.size > 1)
116
- raise "only one argument expected - the class of the node this relationship points to, got #{args.inspect}"
117
- elsif (Class === args[0])
118
- # handle e.g. has_n(:friends).to(class)
119
- @target_class = args[0]
120
- @rel_type = "#{@target_class}##{@method_id}"
121
- else
122
- raise "Expected a class for, got #{args[0]}"
123
- end
124
- self
125
- end
126
-
127
- # Specifies an incoming relationship.
128
- # Will use the outgoing relationship given by the from class.
129
- #
130
- # ==== Example, with prefix FileNode
131
- # class FolderNode
132
- # include Neo4j::NodeMixin
133
- # has_n(:files).to(FileNode)
134
- # end
135
- #
136
- # class FileNode
137
- # include Neo4j::NodeMixin
138
- # # will only traverse any incoming relationship of type files from node FileNode
139
- # has_one(:folder).from(FileNode, :files)
140
- # end
141
- #
142
- # file = FileNode.new
143
- # # create an outgoing relationship of type 'FileNode#files' from folder node to file (FileNode is the prefix).
144
- # file.folder = FolderNode.new
145
- #
146
- # ==== Example, without prefix
147
- #
148
- # class FolderNode
149
- # include Neo4j::NodeMixin
150
- # has_n(:files)
151
- # end
152
- #
153
- # class FileNode
154
- # include Neo4j::NodeMixin
155
- # has_one(:folder).from(:files) # will traverse any incoming relationship of type files
156
- # end
157
- #
158
- # file = FileNode.new
159
- # # create an outgoing relationship of type 'FileNode#files' from folder node to file
160
- # file.folder = FolderNode.new
161
- #
162
- #
163
- def from(*args)
164
- @direction = :incoming
165
-
166
- if (args.size > 1)
167
- # handle specified (prefixed) relationship, e.g. has_n(:known_by).from(clazz, :type)
168
- @rel_type = "#{@target_class}##{args[1]}"
169
- @target_class = args[0]
170
- other_class_dsl = @target_class._decl_rels[args[1]]
171
- if other_class_dsl
172
- @relationship = other_class_dsl.relationship_class
173
- else
174
- puts "WARNING: Unknown outgoing relationship #{args[1]} on #{@target_class}"
175
- end
176
- elsif (Symbol === args[0])
177
- # handle unspecified (unprefixed) relationship, e.g. has_n(:known_by).from(:type)
178
- @rel_type = args[0]
179
- else
180
- raise "Expected a symbol for, got #{args[0]}"
181
- end
182
- self
183
- end
184
-
185
- # Specifies which relationship ruby class to use for the relationship
186
- #
187
- # ==== Example
188
- #
189
- # class OrderLine
190
- # include Neo4j::RelationshipMixin
191
- # property :units
192
- # property :unit_price
193
- # end
194
- #
195
- # class Order
196
- # property :total_cost
197
- # property :dispatched
198
- # has_n(:products).to(Product).relationship(OrderLine)
199
- # end
200
- #
201
- # order = Order.new
202
- # order.products << Product.new
203
- # order.products_rels.first # => OrderLine
204
- #
205
- def relationship(rel_class)
206
- @relationship = rel_class
207
- self
208
- end
209
-
210
- def relationship_class # :nodoc:
211
- @relationship
212
- end
213
- end
214
- end