neo4j 1.0.0.beta.11 → 1.0.0.beta.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/neo4j.rb CHANGED
@@ -50,6 +50,8 @@ require 'neo4j/rails/model'
50
50
  require 'neo4j/rails/value'
51
51
  require 'neo4j/rails/lucene_connection_closer'
52
52
 
53
+ require 'neo4j/model'
54
+
53
55
 
54
56
 
55
57
  # hmm, looks like Enumerator have been moved in some ruby versions
@@ -2,6 +2,7 @@ module Neo4j::Mapping
2
2
  module ClassMethods
3
3
 
4
4
  module Relationship
5
+ include Neo4j::ToJava
5
6
 
6
7
  # Specifies a relationship between two node classes.
7
8
  # Generates assignment and accessor methods for the given relationship.
@@ -24,9 +25,9 @@ module Neo4j::Mapping
24
25
  def has_n(rel_type, params = {})
25
26
  clazz = self
26
27
  module_eval(%Q{
27
- def #{rel_type}(&block)
28
+ def #{rel_type}
28
29
  dsl = #{clazz}._decl_rels[:'#{rel_type.to_s}']
29
- Neo4j::Mapping::HasN.new(self, dsl, &block)
30
+ Neo4j::Mapping::HasN.new(self, dsl)
30
31
  end}, __FILE__, __LINE__)
31
32
 
32
33
  module_eval(%Q{
@@ -61,28 +62,25 @@ module Neo4j::Mapping
61
62
  #
62
63
  def has_one(rel_type, params = {})
63
64
  clazz = self
64
-
65
-
66
65
  module_eval(%Q{def #{rel_type}=(value)
67
- dsl = #{clazz}._decl_rels[:'#{rel_type.to_s}']
68
- r = Neo4j::Mapping::HasN.new(self, dsl)
69
- r.rels.each {|n| n.del} # delete previous relationships, only one can exist
70
- r << value
71
- r
72
- end}, __FILE__, __LINE__)
66
+ dsl = #{clazz}._decl_rels[:'#{rel_type.to_s}']
67
+ rel = dsl.single_relationship(self)
68
+ rel.del unless rel.nil?
69
+ dsl.create_relationship_to(self, value)
70
+ end}, __FILE__, __LINE__)
73
71
 
74
72
  module_eval(%Q{def #{rel_type}
75
- dsl = #{clazz}._decl_rels[:'#{rel_type.to_s}']
76
- r = Neo4j::Mapping::HasN.new(self, dsl)
77
- [*r][0]
78
- end}, __FILE__, __LINE__)
73
+ dsl = #{clazz}._decl_rels[:'#{rel_type.to_s}']
74
+ dsl.single_relationship(self)
75
+ end}, __FILE__, __LINE__)
79
76
 
77
+ # TODO
80
78
  module_eval(%Q{
81
- def #{rel_type}_rel
82
- dsl = #{clazz}._decl_rels[:'#{rel_type.to_s}']
83
- r = Neo4j::Mapping::HasN.new(self, dsl).rels
84
- [*r][0]
85
- end}, __FILE__, __LINE__)
79
+ def #{rel_type}_rel
80
+ dsl = #{clazz}._decl_rels[:'#{rel_type.to_s}']
81
+ r = Neo4j::Mapping::HasN.new(self, dsl).rels
82
+ [*r][0]
83
+ end}, __FILE__, __LINE__)
86
84
 
87
85
  _decl_rels[rel_type.to_sym] = Neo4j::Mapping::DeclRelationshipDsl.new(rel_type, true, params)
88
86
  end
@@ -31,6 +31,7 @@ module Neo4j::Mapping
31
31
  # <b>File#folder</b> :: for accessing nodes from relationship 'files' from the outgoing Folder node
32
32
  #
33
33
  class DeclRelationshipDsl
34
+ include Neo4j::ToJava
34
35
 
35
36
  attr_reader :to_type, :to_class, :cascade_delete_prop_name, :counter, :rel_id, :direction
36
37
  CASCADE_DELETE_PROP_NAMES = {:outgoing => :_cascade_delete_outgoing, :incoming => :_cascade_delete_incoming}
@@ -75,6 +76,41 @@ module Neo4j::Mapping
75
76
  @to_class.nil? ? @to_type.to_s : "#{@to_class.to_s}##{@to_type.to_s}"
76
77
  end
77
78
 
79
+ def each_node(node, direction, &block)
80
+ type = type_to_java(namespace_type)
81
+ dir = dir_to_java(direction)
82
+ node._java_node.getRelationships(type, dir).each do |rel|
83
+ other = rel.getOtherNode(node).wrapper
84
+ block.call other
85
+ end
86
+ end
87
+
88
+ def single_relationship(node)
89
+ type = type_to_java(namespace_type)
90
+ dir = dir_to_java(@direction)
91
+ rel = node._java_node.getSingleRelationship(type, dir)
92
+ rel.nil? ? nil : rel.end_node.wrapper
93
+ end
94
+
95
+ def create_relationship_to(node, other)
96
+ # If the are creating an incoming relationship we need to swap incoming and outgoing nodes
97
+ if @direction == :outgoing
98
+ from, to = node, other
99
+ else
100
+ from, to = other, node
101
+ end
102
+
103
+ java_type = type_to_java(namespace_type)
104
+ rel = from._java_node.create_relationship_to(to._java_node, java_type)
105
+ rel[:_classname] = relationship_class.to_s if relationship_class
106
+
107
+ # TODO - not implemented yet
108
+ # the from.neo_id is only used for cascade_delete_incoming since that node will be deleted when all the list items has been deleted.
109
+ # if cascade_delete_outgoing all nodes will be deleted when the root node is deleted
110
+ # if cascade_delete_incoming then the root node will be deleted when all root nodes' outgoing nodes are deleted
111
+ #rel[@dsl.cascade_delete_prop_name] = node.neo_id if @dsl.cascade_delete?
112
+ rel.wrapper
113
+ end
78
114
 
79
115
  # Specifies an outgoing relationship.
80
116
  # The name of the outgoing class will be used as a prefix for the relationship used.
@@ -11,7 +11,7 @@ module Neo4j
11
11
  def initialize(node, dsl) # :nodoc:
12
12
  @node = node
13
13
  @direction = dsl.direction
14
- # returns the other DSL if it exists otherwise use this DSL for specifing incoming relationships
14
+ # returns the other DSL if it exists otherwise use this DSL for specifying incoming relationships
15
15
  if @direction == :outgoing
16
16
  @dsl = dsl
17
17
  else
@@ -20,8 +20,10 @@ module Neo4j
20
20
  @dsl = clazz._decl_rels[dsl.to_type]
21
21
  raise "Unspecified outgoing relationship '#{dsl.to_type}' for incoming relationship '#{dsl.rel_id}' on class #{clazz}" if @dsl.nil?
22
22
  end
23
+ end
23
24
 
24
- @traverser = Neo4j::NodeTraverser.new(node._java_node, @dsl.namespace_type, @direction)
25
+ def to_s
26
+ "HasN [#@direction, #{@node.neo_id} #{@dsl.namespace_type}]"
25
27
  end
26
28
 
27
29
  def size
@@ -41,6 +43,12 @@ module Neo4j
41
43
  super
42
44
  end
43
45
 
46
+ # Required by the Enumerable mixin.
47
+ def each(&block)
48
+ @dsl.each_node(@node, @direction, &block)
49
+ end
50
+
51
+
44
52
  # Returns the relationships instead of the nodes.
45
53
  #
46
54
  # ==== Example
@@ -51,39 +59,16 @@ module Neo4j
51
59
  Neo4j::RelationshipTraverser.new(@node._java_node, [@dsl.namespace_type], @direction)
52
60
  end
53
61
 
54
- # Sets the depth of the traversal.
55
- # Default is 1 if not specified.
56
- #
57
- # ==== Example
58
- # morpheus.friends.depth(:all).each { ... }
59
- # morpheus.friends.depth(3).each { ... }
60
- #
61
- # ==== Arguments
62
- # d:: the depth or :all if traversing to the end of the network (symbol or fixnum)
63
- # ==== Return
64
- # self
65
- #
66
- def depth(d)
67
- @traverser.depth(d)
68
- self
69
- end
70
-
71
- # Required by the Enumerable mixin.
72
- def each(&block)
73
- @traverser.each(&block)
74
- end
75
-
76
-
77
62
  # Returns true if there are no node in this type of relationship
78
63
  def empty?
79
- @traverser.empty?
64
+ first != nil
80
65
  end
81
66
 
82
67
 
83
68
  # Creates a relationship instance between this and the other node.
84
69
  # Returns the relationship object
85
70
  def new(other)
86
- create_rel(@node, other)
71
+ @dsl.create_relationship_to(@node, other)
87
72
  end
88
73
 
89
74
 
@@ -101,31 +86,9 @@ module Neo4j
101
86
  # self
102
87
  #
103
88
  def <<(other)
104
- create_rel(@node, other)
89
+ @dsl.create_relationship_to(@node, other)
105
90
  self
106
91
  end
107
-
108
-
109
- def create_rel(node, other) # :nodoc:
110
- # If the are creating an incoming relationship we need to swap incoming and outgoing nodes
111
- if @direction == :outgoing
112
- from, to = node, other
113
- else
114
- from, to = other, node
115
- end
116
-
117
- java_type = type_to_java(@dsl.namespace_type)
118
- rel = from._java_node.create_relationship_to(to._java_node, java_type)
119
- rel[:_classname] = @dsl.relationship_class.to_s if @dsl.relationship_class
120
-
121
- # TODO - not implemented yet
122
- # the from.neo_id is only used for cascade_delete_incoming since that node will be deleted when all the list items has been deleted.
123
- # if cascade_delete_outgoing all nodes will be deleted when the root node is deleted
124
- # if cascade_delete_incoming then the root node will be deleted when all root nodes' outgoing nodes are deleted
125
- #rel[@dsl.cascade_delete_prop_name] = node.neo_id if @dsl.cascade_delete?
126
- rel.wrapper
127
- end
128
-
129
92
  end
130
93
 
131
94
  end
@@ -6,7 +6,7 @@ module Neo4j::Mapping
6
6
 
7
7
  def_delegators :@_java_node, :[]=, :[], :property?, :props, :attributes, :update, :neo_id, :id, :rels, :rel?, :to_param, :getId,
8
8
  :rel, :del, :list?, :print, :print_sub, :outgoing, :incoming, :both,
9
- :equal?, :eql?, :==, :exist?, :getRelationships
9
+ :equal?, :eql?, :==, :exist?, :getRelationships, :getSingleRelationship
10
10
 
11
11
 
12
12
  # --------------------------------------------------------------------------
@@ -40,6 +40,10 @@ module Neo4j::Mapping
40
40
  end
41
41
 
42
42
 
43
+ def wrapper
44
+ self
45
+ end
46
+
43
47
  def self.included(c) # :nodoc:
44
48
  c.instance_eval do
45
49
  class << self
@@ -0,0 +1,4 @@
1
+ module Neo4j
2
+ # make an alias so that we don't have to write the long name Neo4j::Rails::Model
3
+ Model = Neo4j::Rails::Model
4
+ end
@@ -132,10 +132,7 @@ module Neo4j
132
132
  end
133
133
 
134
134
  def each
135
- iter = iterator
136
- while (iter.hasNext) do
137
- yield iter.next.wrapper
138
- end
135
+ iterator.each {|i| yield i.wrapper}
139
136
  end
140
137
 
141
138
  def iterator
@@ -147,7 +144,7 @@ module Neo4j
147
144
  end
148
145
  end
149
146
  @td = @td.prune(org.neo4j.kernel.Traversal.pruneAfterDepth( @depth ) ) unless @depth == :all
150
- @td.traverse(@from).nodes.iterator
147
+ @td.traverse(@from).nodes
151
148
  end
152
149
  end
153
150
 
@@ -1,358 +1,343 @@
1
- class Neo4j::Model
2
- include Neo4j::NodeMixin
3
- include ActiveModel::Validations
4
- include ActiveModel::Dirty
5
- include ActiveModel::MassAssignmentSecurity
1
+ module Neo4j
2
+ module Rails
3
+ class Model
4
+ include Neo4j::NodeMixin
5
+ include ActiveModel::Validations
6
+ include ActiveModel::Dirty
7
+ include ActiveModel::MassAssignmentSecurity
6
8
 
7
- extend ActiveModel::Naming
8
- extend ActiveModel::Callbacks
9
- extend Neo4j::Validations::ClassMethods
10
- extend Neo4j::TxMethods
9
+ extend ActiveModel::Naming
10
+ extend ActiveModel::Callbacks
11
+ extend Neo4j::Validations::ClassMethods
12
+ extend TxMethods
13
+ # extend ClassMethods::Relationship
11
14
 
12
- define_model_callbacks :create, :save, :update, :destroy
15
+ define_model_callbacks :create, :save, :update, :destroy
13
16
 
14
17
 
15
- UniquenessValidator = Neo4j::Validations::UniquenessValidator
18
+ UniquenessValidator = Neo4j::Validations::UniquenessValidator
16
19
 
17
- class RecordInvalidError < RuntimeError
18
- attr_reader :record
20
+ class RecordInvalidError < RuntimeError
21
+ attr_reader :record
19
22
 
20
- def initialize(record)
21
- @record = record
22
- super(@record.errors.full_messages.join(", "))
23
- end
24
- end
23
+ def initialize(record)
24
+ @record = record
25
+ super(@record.errors.full_messages.join(", "))
26
+ end
27
+ end
25
28
 
26
- # --------------------------------------
27
- # Initialize
28
- # --------------------------------------
29
+ # --------------------------------------
30
+ # Initialize
31
+ # --------------------------------------
29
32
 
30
- def initialize(*)
31
- end
33
+ def initialize(*)
34
+ end
32
35
 
33
- def init_on_create(*args) # :nodoc:
34
- super()
35
- self.attributes=args[0] if args[0].respond_to?(:each_pair)
36
- @_created_record = true
37
- end
36
+ def init_on_create(*args) # :nodoc:
37
+ super()
38
+ self.attributes=args[0] if args[0].respond_to?(:each_pair)
39
+ @_created_record = true
40
+ end
38
41
 
39
- # --------------------------------------
40
- # Identity
41
- # --------------------------------------
42
+ # --------------------------------------
43
+ # Identity
44
+ # --------------------------------------
42
45
 
43
- def id
44
- neo_id.nil? ? nil : neo_id.to_s
45
- end
46
+ def id
47
+ neo_id.nil? ? nil : neo_id.to_s
48
+ end
46
49
 
47
- def to_param
48
- persisted? ? neo_id.to_s : nil
49
- end
50
+ def to_param
51
+ persisted? ? neo_id.to_s : nil
52
+ end
50
53
 
51
- # Returns an Enumerable of all (primary) key attributes
52
- # or nil if model.persisted? is false
53
- def to_key
54
- persisted? ? [:id] : nil
55
- end
54
+ # Returns an Enumerable of all (primary) key attributes
55
+ # or nil if model.persisted? is false
56
+ def to_key
57
+ persisted? ? [:id] : nil
58
+ end
56
59
 
57
60
 
58
- # enables ActiveModel::Dirty and Validation
59
- def method_missing(method_id, *args, &block)
60
- if !self.class.attribute_methods_generated?
61
- self.class.define_attribute_methods(self.class._decl_props.keys)
62
- # try again
63
- send(method_id, *args, &block)
64
- end
65
- end
66
-
67
- # redefine this methods so that ActiveModel::Dirty will work
68
- def []=(key, new_value)
69
- key = key.to_s
70
- unless key[0] == ?_
71
- old_value = self.send(:[], key)
72
- attribute_will_change!(key) unless old_value == new_value
73
- end
74
- Neo4j::Rails::Transaction.running? ? super : Neo4j::Rails::Transaction.run { super }
75
- end
61
+ # enables ActiveModel::Dirty and Validation
62
+ def method_missing(method_id, *args, &block)
63
+ if !self.class.attribute_methods_generated?
64
+ self.class.define_attribute_methods(self.class._decl_props.keys)
65
+ # try again
66
+ send(method_id, *args, &block)
67
+ end
68
+ end
76
69
 
77
- def attribute_will_change!(attr)
78
- begin
79
- value = __send__(:[], attr)
80
- value = value.duplicable? ? value.clone : value
81
- rescue TypeError, NoMethodError
82
- end
83
- changed_attributes[attr] = value
84
- end
70
+ # redefine this methods so that ActiveModel::Dirty will work
71
+ def []=(key, new_value)
72
+ key = key.to_s
73
+ unless key[0] == ?_
74
+ old_value = self.send(:[], key)
75
+ attribute_will_change!(key) unless old_value == new_value
76
+ end
77
+ Neo4j::Rails::Transaction.running? ? super : Neo4j::Rails::Transaction.run { super }
78
+ end
85
79
 
80
+ def attribute_will_change!(attr)
81
+ begin
82
+ value = __send__(:[], attr)
83
+ value = value.duplicable? ? value.clone : value
84
+ rescue TypeError, NoMethodError
85
+ end
86
+ changed_attributes[attr] = value
87
+ end
86
88
 
87
- def read_attribute_for_validation(key)
88
- respond_to?(key) ? send(key) : self[key]
89
- end
90
89
 
91
- def attributes=(values)
92
- sanitize_for_mass_assignment(values).each do |k, v|
93
- if respond_to?("#{k}=")
94
- send("#{k}=", v)
95
- else
96
- self[k] = v
90
+ def read_attribute_for_validation(key)
91
+ respond_to?(key) ? send(key) : self[key]
97
92
  end
98
- end
99
- end
100
93
 
94
+ def attributes=(values)
95
+ sanitize_for_mass_assignment(values).each do |k, v|
96
+ if respond_to?("#{k}=")
97
+ send("#{k}=", v)
98
+ else
99
+ self[k] = v
100
+ end
101
+ end
102
+ end
101
103
 
102
- # Updates this resource with all the attributes from the passed-in Hash and requests that the record be saved.
103
- # If saving fails because the resource is invalid then false will be returned.
104
- def update_attributes(attributes)
105
- self.attributes=attributes
106
- save
107
- end
108
104
 
109
- def update_attributes!(attributes)
110
- self.attributes=attributes
111
- save!
112
- end
105
+ # Updates this resource with all the attributes from the passed-in Hash and requests that the record be saved.
106
+ # If saving fails because the resource is invalid then false will be returned.
107
+ def update_attributes(attributes)
108
+ self.attributes=attributes
109
+ save
110
+ end
113
111
 
114
- def update_nested_attributes(rel_type, clazz, has_one, attr, options)
115
- allow_destroy,reject_if = [options[:allow_destroy], options[:reject_if]] if options
116
-
117
- if new?
118
- # We are updating a node that was created with the 'new' method.
119
- # The relationship will only be kept in the Value object.
120
- outgoing(rel_type)<<clazz.new(attr) unless reject_if?(reject_if,attr)
121
- else
122
- # We have a node that was created with the #create method - has real Neo4j relationships
123
- # does it exist ?
124
- found = if has_one
125
- # id == nil that means we have a has_one relationship
126
- outgoing(rel_type).first
127
- else
128
- # do we have an ID ?
129
- id = attr[:id]
130
- # this is a has_n relationship, find which one we want to update
131
- id && outgoing(rel_type).find { |n| n.id == id }
132
- end
112
+ def update_attributes!(attributes)
113
+ self.attributes=attributes
114
+ save!
115
+ end
133
116
 
134
- # Check if we want to destroy not found nodes (e.g. {..., :_destroy => '1' } ?
135
- destroy = attr[:_destroy] && attr[:_destroy] != '0'
117
+ def update_nested_attributes(rel_type, clazz, has_one, attr, options)
118
+ allow_destroy, reject_if = [options[:allow_destroy], options[:reject_if]] if options
136
119
 
137
- if found
138
- if destroy
139
- found.destroy if allow_destroy
120
+ if new?
121
+ # We are updating a node that was created with the 'new' method.
122
+ # The relationship will only be kept in the Value object.
123
+ outgoing(rel_type)<<clazz.new(attr) unless reject_if?(reject_if, attr)
140
124
  else
141
- found.update_attributes_in_tx(attr) # it already exist, so update that one
125
+ # We have a node that was created with the #create method - has real Neo4j relationships
126
+ # does it exist ?
127
+ found = if has_one
128
+ # id == nil that means we have a has_one relationship
129
+ outgoing(rel_type).first
130
+ else
131
+ # do we have an ID ?
132
+ id = attr[:id]
133
+ # this is a has_n relationship, find which one we want to update
134
+ id && outgoing(rel_type).find { |n| n.id == id }
135
+ end
136
+
137
+ # Check if we want to destroy not found nodes (e.g. {..., :_destroy => '1' } ?
138
+ destroy = attr[:_destroy] && attr[:_destroy] != '0'
139
+
140
+ puts "FOUND #{found}"
141
+ if found
142
+ if destroy
143
+ found.destroy if allow_destroy
144
+ else
145
+ found.update_attributes_in_tx(attr) # it already exist, so update that one
146
+ end
147
+ elsif !destroy && !reject_if?(reject_if, attr)
148
+ new_node = clazz.new(attr)
149
+ saved = new_node.save
150
+ outgoing(rel_type) << new_node if saved
151
+ end
142
152
  end
143
- elsif !destroy && !reject_if?(reject_if,attr)
144
- new_node = clazz.new(attr)
145
- saved = new_node.save
146
- outgoing(rel_type) << new_node if saved
147
153
  end
148
- end
149
- end
150
-
151
- def reject_if?(proc_or_symbol, attr)
152
- return false if proc_or_symbol.nil?
153
- if proc_or_symbol.is_a?(Symbol)
154
- meth = method(proc_or_symbol)
155
- meth.arity == 0 ? meth.call : meth.call(attr)
156
- else
157
- proc_or_symbol.call(attr)
158
- end
159
- end
160
-
161
- def delete
162
- super
163
- @_deleted = true
164
- @_persisted = false
165
- end
166
154
 
167
- def save
168
- valid = valid?
169
- if valid
170
- # if we are trying to save a value then we should create a real node
171
- valid = _run_save_callbacks { create_or_update_node }
172
- @_created_record = false
173
- true
174
- else
175
- # if not valid we should rollback the transaction so that the changes does not take place.
176
- # no point failing the transaction if we have created a model with 'new'
177
- Neo4j::Rails::Transaction.fail if Neo4j::Rails::Transaction.running? && !_java_node.kind_of?(Neo4j::Value)
178
- false
179
- end
180
- valid
181
- end
155
+ def reject_if?(proc_or_symbol, attr)
156
+ return false if proc_or_symbol.nil?
157
+ if proc_or_symbol.is_a?(Symbol)
158
+ meth = method(proc_or_symbol)
159
+ meth.arity == 0 ? meth.call : meth.call(attr)
160
+ else
161
+ proc_or_symbol.call(attr)
162
+ end
163
+ end
182
164
 
183
- def create_or_update_node
184
- valid = true
185
- if _java_node.kind_of?(Neo4j::Value)
186
- node = Neo4j::Node.new(props)
187
- valid = _java_node.save_nested(node)
188
- init_on_load(node)
189
- init_on_create
190
- end
165
+ def delete
166
+ super
167
+ @_deleted = true
168
+ @_persisted = false
169
+ end
191
170
 
192
- if new_record?
193
- _run_create_callbacks { clear_changes }
194
- else
195
- _run_update_callbacks { clear_changes }
196
- end
197
- valid
198
- end
171
+ def save
172
+ valid = valid?
173
+ if valid
174
+ # if we are trying to save a value then we should create a real node
175
+ valid = _run_save_callbacks { create_or_update_node }
176
+ @_created_record = false
177
+ true
178
+ else
179
+ # if not valid we should rollback the transaction so that the changes does not take place.
180
+ # no point failing the transaction if we have created a model with 'new'
181
+ Neo4j::Rails::Transaction.fail if Neo4j::Rails::Transaction.running? && !_java_node.kind_of?(Neo4j::Rails::Value)
182
+ false
183
+ end
184
+ valid
185
+ end
199
186
 
200
- def clear_changes
201
- @previously_changed = changes
202
- @changed_attributes.clear
203
- end
187
+ def create_or_update_node
188
+ valid = true
189
+ if _java_node.kind_of?(Neo4j::Rails::Value)
190
+ node = Neo4j::Node.new(props)
191
+ valid = _java_node.save_nested(node)
192
+ init_on_load(node)
193
+ init_on_create
194
+ end
204
195
 
205
- def save!
206
- raise RecordInvalidError.new(self) unless save
207
- end
196
+ if new_record?
197
+ _run_create_callbacks { clear_changes }
198
+ else
199
+ _run_update_callbacks { clear_changes }
200
+ end
201
+ valid
202
+ end
208
203
 
209
- # Returns if the record is persisted, i.e. it’s not a new record and it was not destroyed
210
- def persisted?
211
- !new_record? && !destroyed?
212
- end
204
+ def clear_changes
205
+ @previously_changed = changes
206
+ @changed_attributes.clear
207
+ end
213
208
 
214
- def to_model
215
- self
216
- end
209
+ def save!
210
+ raise RecordInvalidError.new(self) unless save
211
+ end
217
212
 
218
- # Returns true if this object hasn’t been saved yet that is, a record for the object doesn’t exist yet; otherwise, returns false.
219
- def new_record?()
220
- # it is new if the model has been created with either the new or create method
221
- new? || @_created_record == true
222
- end
213
+ # Returns if the record is persisted, i.e. it’s not a new record and it was not destroyed
214
+ def persisted?
215
+ !new_record? && !destroyed?
216
+ end
223
217
 
224
- def new?
225
- _java_node.kind_of?(Neo4j::Value)
226
- end
218
+ def to_model
219
+ self
220
+ end
227
221
 
228
- def del
229
- @_deleted = true
230
- super
231
- end
222
+ # Returns true if this object hasn’t been saved yet — that is, a record for the object doesn’t exist yet; otherwise, returns false.
223
+ def new_record?()
224
+ # it is new if the model has been created with either the new or create method
225
+ new? || @_created_record == true
226
+ end
232
227
 
233
- def destroy
234
- _run_update_callbacks { del }
235
- end
228
+ def new?
229
+ _java_node.kind_of?(Neo4j::Rails::Value)
230
+ end
236
231
 
237
- def destroyed?()
238
- @_deleted
239
- end
232
+ def del
233
+ @_deleted = true
234
+ super
235
+ end
240
236
 
241
- tx_methods :destroy, :create_or_update_node, :update_attributes, :update_attributes!
237
+ def destroy
238
+ _run_update_callbacks { del }
239
+ end
242
240
 
243
- # --------------------------------------
244
- # Class Methods
245
- # --------------------------------------
241
+ def destroyed?()
242
+ @_deleted
243
+ end
246
244
 
247
- class << self
248
- extend Neo4j::TxMethods
245
+ tx_methods :destroy, :create_or_update_node, :update_attributes, :update_attributes!
249
246
 
250
- # returns a value object instead of creating a new node
251
- def new(*args)
252
- value = Neo4j::Value.new
253
- wrapped = self.orig_new
254
- wrapped.init_on_load(value)
255
- wrapped.attributes=args[0] if args[0].respond_to?(:each_pair)
247
+ # --------------------------------------
248
+ # Class Methods
249
+ # --------------------------------------
256
250
 
257
- wrapped.class._decl_rels.each_pair do |field, dsl|
251
+ class << self
252
+ extend TxMethods
258
253
 
259
- meta = class << wrapped;
260
- self;
254
+ # returns a value object instead of creating a new node
255
+ def new(*args)
256
+ wrapped = self.orig_new
257
+ value = Neo4j::Rails::Value.new(wrapped)
258
+ wrapped.init_on_load(value)
259
+ wrapped.attributes=args[0] if args[0].respond_to?(:each_pair)
260
+ wrapped
261
261
  end
262
262
 
263
- wrapped.class._decl_rels.each_pair do |field, dsl|
264
- meta.send(:define_method, field) do
265
- if new?
266
- value.outgoing(dsl.namespace_type)
267
- else
268
- self.outgoing(dsl.namespace_type)
269
- end
270
- end if dsl.direction == :outgoing
271
-
272
- meta.send(:define_method, field) do
273
- raise "NOT IMPLEMENTED #{field} (incoming relationship) FOR #new method, please create a new model with the create method instead"
274
- end if dsl.direction == :incoming
263
+ # Handle Model.find(params[:id])
264
+ def find(*args)
265
+ if args.length == 1 && String === args[0] && args[0].to_i != 0
266
+ load(*args)
267
+ else
268
+ hits = super
269
+ # We need to save this so that the Rack Neo4j::Rails:LuceneConnection::Closer can close it
270
+ Thread.current[:neo4j_lucene_connection] ||= []
271
+ Thread.current[:neo4j_lucene_connection] << hits
272
+ hits
273
+ end
275
274
  end
276
- end
277
-
278
- wrapped
279
- end
280
275
 
281
- # Handle Model.find(params[:id])
282
- def find(*args)
283
- if args.length == 1 && String === args[0] && args[0].to_i != 0
284
- load(*args)
285
- else
286
- hits = super
287
- # We need to save this so that the Rack Neo4j::Rails:LuceneConnection::Closer can close it
288
- Thread.current[:neo4j_lucene_connection] ||= []
289
- Thread.current[:neo4j_lucene_connection] << hits
290
- hits
291
- end
292
- end
293
-
294
- def load(*ids)
295
- result = ids.map { |id| Neo4j::Node.load(id) }
296
- if ids.length == 1
297
- result.first
298
- else
299
- result
300
- end
301
- end
276
+ def load(*ids)
277
+ result = ids.map { |id| Neo4j::Node.load(id) }
278
+ if ids.length == 1
279
+ result.first
280
+ else
281
+ result
282
+ end
283
+ end
302
284
 
303
285
 
304
- alias_method :_orig_create, :create
286
+ alias_method :_orig_create, :create
305
287
 
306
- def create(*)
307
- model = super
308
- model.save
309
- model
310
- end
288
+ def create(*)
289
+ model = super
290
+ model.save
291
+ model
292
+ end
311
293
 
312
- def create!(*args)
313
- model = _orig_create(*args)
314
- model.save!
315
- model
316
- end
294
+ def create!(*args)
295
+ model = _orig_create(*args)
296
+ model.save!
297
+ model
298
+ end
317
299
 
318
- tx_methods :create, :create!
300
+ tx_methods :create, :create!
319
301
 
320
302
 
321
- def transaction(&block)
322
- Neo4j::Rails::Transaction.run &block
323
- end
303
+ def transaction(&block)
304
+ Neo4j::Rails::Transaction.run &block
305
+ end
324
306
 
325
- def accepts_nested_attributes_for(*attr_names)
326
- options = attr_names.pop if attr_names[-1].is_a?(Hash)
307
+ def accepts_nested_attributes_for(*attr_names)
308
+ options = attr_names.pop if attr_names[-1].is_a?(Hash)
327
309
 
328
- attr_names.each do |association_name|
329
- rel = self._decl_rels[association_name.to_sym]
330
- raise "No relationship declared with has_n or has_one with type #{association_name}" unless rel
331
- to_class = rel.to_class
332
- raise "Can't use accepts_nested_attributes_for(#{association_name}) since it has not defined which class it has a relationship to, use has_n(#{association_name}).to(MyOtherClass)" unless to_class
333
- type = rel.namespace_type
334
- has_one = rel.has_one?
310
+ attr_names.each do |association_name|
311
+ rel = self._decl_rels[association_name.to_sym]
312
+ raise "No relationship declared with has_n or has_one with type #{association_name}" unless rel
313
+ to_class = rel.to_class
314
+ raise "Can't use accepts_nested_attributes_for(#{association_name}) since it has not defined which class it has a relationship to, use has_n(#{association_name}).to(MyOtherClass)" unless to_class
315
+ type = rel.namespace_type
316
+ has_one = rel.has_one?
335
317
 
336
- send(:define_method, "#{association_name}_attributes=") do |attributes|
337
- if has_one
338
- update_nested_attributes(type, to_class, true, attributes, options)
339
- else
340
- if attributes.is_a?(Array)
341
- attributes.each do |attr|
342
- update_nested_attributes(type, to_class, false, attr, options)
343
- end
344
- else
345
- attributes.each_value do |attr|
346
- update_nested_attributes(type, to_class, false, attr, options)
318
+ send(:define_method, "#{association_name}_attributes=") do |attributes|
319
+ if has_one
320
+ update_nested_attributes(type, to_class, true, attributes, options)
321
+ else
322
+ if attributes.is_a?(Array)
323
+ attributes.each do |attr|
324
+ update_nested_attributes(type, to_class, false, attr, options)
325
+ end
326
+ else
327
+ attributes.each_value do |attr|
328
+ update_nested_attributes(type, to_class, false, attr, options)
329
+ end
330
+ end
347
331
  end
348
332
  end
333
+ tx_methods("#{association_name}_attributes=")
349
334
  end
350
335
  end
351
- tx_methods("#{association_name}_attributes=")
336
+
352
337
  end
338
+
353
339
  end
354
340
 
355
341
  end
356
-
357
342
  end
358
343
 
@@ -1,11 +1,15 @@
1
- module Neo4j::TxMethods
2
- def tx_methods(*methods)
3
- methods.each do |method|
4
- tx_method = "#{method}_in_tx"
5
- send(:alias_method, tx_method, method)
6
- send(:define_method, method) do |*args|
7
- Neo4j::Rails::Transaction.running? ? send(tx_method, *args) : Neo4j::Rails::Transaction.run { send(tx_method, *args) }
1
+ module Neo4j
2
+ module Rails
3
+ module TxMethods
4
+ def tx_methods(*methods)
5
+ methods.each do |method|
6
+ tx_method = "#{method}_in_tx"
7
+ send(:alias_method, tx_method, method)
8
+ send(:define_method, method) do |*args|
9
+ Neo4j::Rails::Transaction.running? ? send(tx_method, *args) : Neo4j::Rails::Transaction.run { send(tx_method, *args) }
10
+ end
11
+ end
8
12
  end
9
13
  end
10
14
  end
11
- end
15
+ end
@@ -1,16 +1,13 @@
1
- module Neo4j
1
+ module Neo4j::Rails
2
2
 
3
3
  class Value
4
4
  include Neo4j::Property
5
5
  include org.neo4j.graphdb.Node
6
6
 
7
- def initialize(*args)
8
- # the first argument can be an hash of properties to set
7
+ def initialize(wrapper)
8
+ @wrapper = wrapper
9
9
  @props = {}
10
- if args[0].respond_to?(:each_pair)
11
- args[0].each_pair { |k, v| set_property(k.to_s, v) }
12
- end
13
- @rels = {} # a hash of all relationship with key type
10
+ @outgoing_rels = {} # a hash of all relationship with key type
14
11
  end
15
12
 
16
13
  # override Neo4j::Property#props
@@ -22,6 +19,23 @@ module Neo4j
22
19
  nil
23
20
  end
24
21
 
22
+
23
+ def create_relationship_to(other_java_node, java_type)
24
+ outgoing(java_type.name).new(other_java_node)
25
+ end
26
+
27
+ def getSingleRelationship(type, dir)
28
+ # TODO incoming not implemented, needed ?
29
+ @outgoing_rels[type.name] && @outgoing_rels[type.name].rels.first
30
+ end
31
+
32
+ def getRelationships(*args)
33
+ type = args[0].name
34
+ outgoing = @outgoing_rels[type]
35
+ return [] unless outgoing
36
+ outgoing.rels
37
+ end
38
+
25
39
  # Pretend this object is a Java Node
26
40
  def has_property?(key)
27
41
  !@props[key].nil?
@@ -39,16 +53,22 @@ module Neo4j
39
53
  @props.delete(key)
40
54
  end
41
55
 
56
+ def wrapper
57
+ @wrapper
58
+ end
59
+
42
60
  def outgoing(type)
43
- @rels[type.to_sym] ||= OutgoingRels.new
61
+ @outgoing_rels[type.to_s] ||= OutgoingRels.new(self)
44
62
  end
45
63
 
46
64
  def save_nested(root_node)
47
65
  valid = true
48
- @rels.each_pair do |type, rel|
66
+ @outgoing_rels.each_pair do |type, rel|
49
67
  rel.each do |new_node|
50
- if new_node.save
51
- root_node.outgoing(type) << new_node
68
+ wrapper = new_node.respond_to?(:wrapper) ? new_node.wrapper : new_node
69
+ if wrapper.save
70
+ puts "NEW RELATIONSHIP OF TYPE #{type} from #{root_node} to #{new_node}"
71
+ root_node.outgoing(type) << wrapper
52
72
  else
53
73
  valid = false
54
74
  end
@@ -57,22 +77,55 @@ module Neo4j
57
77
  valid
58
78
  end
59
79
 
80
+ class Relationship
81
+ include org.neo4j.graphdb.Relationship
82
+ attr_reader :end_node, :start_node
83
+
84
+ def initialize(from, to)
85
+ @end_node = to
86
+ @start_node = from
87
+ end
88
+
89
+ def wrapper
90
+ self
91
+ end
92
+
93
+ def getOtherNode(other)
94
+ other == @end_node ? @start_node : @end_node
95
+ end
96
+ end
97
+
98
+
60
99
  class OutgoingRels
61
100
  include Enumerable
62
- def initialize
63
- @nodes = []
101
+ attr_reader :rels
102
+
103
+ def initialize(start_node)
104
+ @rels = []
105
+ @start_node = start_node
64
106
  end
65
107
 
66
108
  def <<(other)
67
- @nodes << other
109
+ new(other)
110
+ self
111
+ end
112
+
113
+ def new(other)
114
+ new_rel = Relationship.new(@start_node, other)
115
+ @rels << new_rel
116
+ new_rel
68
117
  end
69
118
 
70
119
  def each
71
- @nodes.each {|n| yield n}
120
+ @rels.each {|n| yield n.end_node}
121
+ end
122
+
123
+ def clear
124
+ @rels.clear
72
125
  end
73
126
 
74
127
  def empty?
75
- @nodes.empty?
128
+ @rels.empty?
76
129
  end
77
130
 
78
131
  def is_a?(type)
@@ -16,10 +16,7 @@ module Neo4j
16
16
  end
17
17
 
18
18
  def each
19
- iter = iterator
20
- while (iter.hasNext) do
21
- yield iter.next.wrapper
22
- end
19
+ iterator.each {|i| yield i.wrapper}
23
20
  end
24
21
 
25
22
  def iterator
data/lib/neo4j/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Neo4j
2
- VERSION = "1.0.0.beta.11"
2
+ VERSION = "1.0.0.beta.12"
3
3
  end
metadata CHANGED
@@ -7,8 +7,8 @@ version: !ruby/object:Gem::Version
7
7
  - 0
8
8
  - 0
9
9
  - beta
10
- - 11
11
- version: 1.0.0.beta.11
10
+ - 12
11
+ version: 1.0.0.beta.12
12
12
  platform: ruby
13
13
  authors:
14
14
  - Andreas Ronge
@@ -16,7 +16,7 @@ autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
18
 
19
- date: 2010-10-08 00:00:00 +02:00
19
+ date: 2010-10-12 00:00:00 +02:00
20
20
  default_executable:
21
21
  dependencies:
22
22
  - !ruby/object:Gem::Dependency
@@ -102,6 +102,7 @@ extra_rdoc_files:
102
102
  files:
103
103
  - lib/neo4j.rb
104
104
  - lib/neo4j/event_handler.rb
105
+ - lib/neo4j/model.rb
105
106
  - lib/neo4j/node_traverser.rb
106
107
  - lib/neo4j/relationship_traverser.rb
107
108
  - lib/neo4j/config.rb