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

Sign up to get free protection for your applications and to get access to all the features.
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