neo4j 1.3.0-java → 1.3.1-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/CHANGELOG +14 -0
  2. data/CONTRIBUTORS +1 -0
  3. data/Gemfile +7 -0
  4. data/README.rdoc +6 -3
  5. data/lib/neo4j.rb +13 -13
  6. data/lib/neo4j/algo/algo.rb +2 -2
  7. data/lib/neo4j/database.rb +1 -1
  8. data/lib/neo4j/has_n/decl_relationship_dsl.rb +11 -8
  9. data/lib/neo4j/identity_map.rb +0 -3
  10. data/lib/neo4j/index/lucene_query.rb +50 -9
  11. data/lib/neo4j/jars/core/{neo4j-community-1.5.jar → neo4j-community-1.6.M01.jar} +0 -0
  12. data/lib/neo4j/jars/core/{neo4j-cypher-1.5.jar → neo4j-cypher-1.6.M01.jar} +0 -0
  13. data/lib/neo4j/jars/core/{neo4j-graph-algo-1.5.jar → neo4j-graph-algo-1.6.M01.jar} +0 -0
  14. data/lib/neo4j/jars/core/{neo4j-graph-matching-1.5.jar → neo4j-graph-matching-1.6.M01.jar} +0 -0
  15. data/lib/neo4j/jars/core/{neo4j-jmx-1.5.jar → neo4j-jmx-1.6.M01.jar} +0 -0
  16. data/lib/neo4j/jars/core/{neo4j-kernel-1.5.jar → neo4j-kernel-1.6.M01.jar} +0 -0
  17. data/lib/neo4j/jars/core/{neo4j-lucene-index-1.5.jar → neo4j-lucene-index-1.6.M01.jar} +0 -0
  18. data/lib/neo4j/jars/core/{neo4j-shell-1.5.jar → neo4j-shell-1.6.M01.jar} +0 -0
  19. data/lib/neo4j/jars/core/{neo4j-udc-1.5.jar → neo4j-udc-1.6.M01.jar} +0 -0
  20. data/lib/neo4j/jars/core/{server-api-1.5.jar → server-api-1.6.M01.jar} +0 -0
  21. data/lib/neo4j/jars/ha/{neo4j-backup-1.5.jar → neo4j-backup-1.6.M01.jar} +0 -0
  22. data/lib/neo4j/jars/ha/{neo4j-com-1.5.jar → neo4j-com-1.6.M01.jar} +0 -0
  23. data/lib/neo4j/jars/ha/{neo4j-enterprise-1.5.jar → neo4j-enterprise-1.6.M01.jar} +0 -0
  24. data/lib/neo4j/jars/ha/neo4j-ha-1.6.M01.jar +0 -0
  25. data/lib/neo4j/jars/ha/{neo4j-management-1.5.jar → neo4j-management-1.6.M01.jar} +0 -0
  26. data/lib/neo4j/jars/neo4j-community-1.6.M01.jar +0 -0
  27. data/lib/neo4j/rails/accept_id.rb +66 -0
  28. data/lib/neo4j/rails/mapping/property.rb +1 -2
  29. data/lib/neo4j/rails/model.rb +1 -0
  30. data/lib/neo4j/rails/observer.rb +61 -2
  31. data/lib/neo4j/rails/persistence.rb +1 -1
  32. data/lib/neo4j/rails/rails.rb +1 -0
  33. data/lib/neo4j/rails/rel_persistence.rb +10 -11
  34. data/lib/neo4j/rails/relationships/node_dsl.rb +5 -1
  35. data/lib/neo4j/rails/relationships/relationships.rb +34 -0
  36. data/lib/neo4j/rails/relationships/storage.rb +34 -5
  37. data/lib/neo4j/type_converters/type_converters.rb +49 -4
  38. data/lib/neo4j/version.rb +1 -1
  39. metadata +19 -17
  40. data/lib/neo4j/jars/ha/neo4j-ha-1.5.jar +0 -0
data/CHANGELOG CHANGED
@@ -1,3 +1,17 @@
1
+ == 1.3.1 / 2011-12-14
2
+ * Make all relationships visible in Rails callback (rspecs #87, Dmytrii Nagirniak) [#211]
3
+ * Enable travis to build JRuby 1.9 (pull #87, Dmytrii Nagirniak) [#214]
4
+ * Support for composite lucene queries with OR and NOT (pull #89, Deepak N)
5
+ * Enforce the correct converter on a property type when the type is given (pull #86, Dmytrii Nagirniak)
6
+ * Development: make it easier to run RSpecs and guard (pull #85, Dmytrii Nagirniak)
7
+ * Added ability to disable observer (pull #84, Dmytrii Nagirniak)
8
+ * Fixing multiple assignment of has_one assocaition (pull #83 Deepak N)
9
+ * Accept association_id for has_one assocations (pull #82, Deepak N)
10
+ * Upgrade to 1.6.M01 Neo4j java jars [#209]
11
+ * Defer warning message 'Unknown outgoing relationship' (pull #81, Vivek Prahlad)
12
+ * Added string converter, e.g. property :name, :type => String (pull #80, Dmytrii Nagirniak)
13
+ * Added symbol converter e.g. property :status, :type => Symbol (pull #79, Dmytrii Nagirniak) [#205]
14
+
1
15
  == 1.3.0 / 2011-12-06
2
16
  * Added neo4j-upgrade script to rename lucene index files and upgrade to 1.5 [#197]
3
17
  * Expose Neo4j::NodeMixin#index_types returning available indices (useful for Cypher queries) [#194]
data/CONTRIBUTORS CHANGED
@@ -2,6 +2,7 @@ Maintainer:
2
2
  Andreas Ronge <andreas dot ronge at gmail dot com>
3
3
 
4
4
  Contributors:
5
+ * Dmytrii Nagirniak
5
6
  * Marcio Toshio
6
7
  * Kalyan Akella
7
8
  * Vivek Prahlad
data/Gemfile CHANGED
@@ -8,6 +8,13 @@ group 'test' do
8
8
  gem "horo", ">= 1.0.2"
9
9
  gem "rspec", "= 2.6.0"
10
10
 
11
+ gem 'guard'
12
+ gem 'ruby_gntp', :require => false # GrowlNotify for Mac
13
+ gem 'rb-inotify', :require => false
14
+ gem 'rb-fsevent', :require => false
15
+ gem 'rb-fchange', :require => false
16
+ gem "guard-rspec"
17
+
11
18
  # use this version for rspec-rails-matchers which work with latest RSpec (Rspec => RSpec)
12
19
  gem "rspec-rails-matchers", :git => 'git://github.com/afcapel/rspec-rails-matchers.git'
13
20
 
data/README.rdoc CHANGED
@@ -126,17 +126,20 @@ Notice that you can always access the lower layers if you want to do some more a
126
126
 
127
127
  === Project information
128
128
  * {GitHub}[http://github.com/andreasronge/neo4j/tree/master]
129
- * {Lighthouse Issue Tracking}[http://neo4j.lighthouseapp.com]
129
+ * {Issue Tracking}[https://github.com/andreasronge/neo4j/issues]
130
130
  * {Twitter}[http://twitter.com/ronge]
131
- * IRC - #neo4j @ irc.freenode.net
132
131
  * {Mailing list, neo4jrb@googlegroups.com}[http://groups.google.com/group/neo4jrb]
132
+ * {Read only, old lighthouse issues}[http://neo4j.lighthouseapp.com]
133
133
 
134
134
  === Contributing
135
135
 
136
+ {<img src="https://secure.travis-ci.org/andreasronge/neo4j.png" />}[http://travis-ci.org/andreasronge/neo4j]
137
+
138
+ {Development configuration}[http://neo4j.rubyforge.org/guides/index.html#development-and-testing-configuration]
139
+
136
140
  Have you found a bug, need help or have a patch ?
137
141
  Just clone neo4j.rb and send me a pull request or email me.
138
142
  Do you need help - send me an email (andreas.ronge at gmail dot com).
139
- Please also check/add issues at lighthouse, http://neo4j.lighthouseapp.com
140
143
 
141
144
  === License
142
145
  * Neo4j.rb - MIT, see the LICENSE file http://github.com/andreasronge/neo4j/tree/master/LICENSE.
data/lib/neo4j.rb CHANGED
@@ -20,15 +20,15 @@ require 'neo4j/core_ext/class/inheritable_attributes'
20
20
 
21
21
  require 'neo4j/jars/core/geronimo-jta_1.1_spec-1.1.1.jar'
22
22
  require 'neo4j/jars/core/lucene-core-3.1.0.jar'
23
- require 'neo4j/jars/core/neo4j-cypher-1.5.jar'
24
- require 'neo4j/jars/core/neo4j-kernel-1.5.jar'
25
- require 'neo4j/jars/core/neo4j-lucene-index-1.5.jar'
26
- require 'neo4j/jars/core/neo4j-jmx-1.5.jar'
27
- require 'neo4j/jars/core/neo4j-udc-1.5.jar'
23
+ require 'neo4j/jars/core/neo4j-cypher-1.6.M01.jar'
24
+ require 'neo4j/jars/core/neo4j-kernel-1.6.M01.jar'
25
+ require 'neo4j/jars/core/neo4j-lucene-index-1.6.M01.jar'
26
+ require 'neo4j/jars/core/neo4j-jmx-1.6.M01.jar'
27
+ require 'neo4j/jars/core/neo4j-udc-1.6.M01.jar'
28
28
  require 'neo4j/jars/core/org.apache.servicemix.bundles.jline-0.9.94_1.jar'
29
29
  require 'neo4j/jars/core/scala-library-2.9.0-1.jar'
30
- require 'neo4j/jars/core/server-api-1.5.jar'
31
- require 'neo4j/jars/ha/neo4j-management-1.5.jar'
30
+ require 'neo4j/jars/core/server-api-1.6.M01.jar'
31
+ require 'neo4j/jars/ha/neo4j-management-1.6.M01.jar'
32
32
 
33
33
  module Neo4j
34
34
 
@@ -39,20 +39,20 @@ module Neo4j
39
39
  end
40
40
 
41
41
  def self.load_shell_jars
42
- require 'neo4j/jars/core/neo4j-shell-1.5.jar'
42
+ require 'neo4j/jars/core/neo4j-shell-1.6.M01.jar'
43
43
  end
44
44
 
45
45
  def self.load_online_backup
46
- require 'neo4j/jars/ha/neo4j-com-1.5.jar'
47
- require 'neo4j/jars/ha/neo4j-backup-1.5.jar'
46
+ require 'neo4j/jars/ha/neo4j-com-1.6.M01.jar'
47
+ require 'neo4j/jars/ha/neo4j-backup-1.6.M01.jar'
48
48
  require 'neo4j/jars/ha/org.apache.servicemix.bundles.netty-3.2.5.Final_1.jar'
49
49
  Neo4j.send(:const_set, :OnlineBackup, org.neo4j.backup.OnlineBackup)
50
50
  end
51
51
 
52
52
  def self.load_ha_jars
53
- require 'neo4j/jars/ha/neo4j-backup-1.5.jar'
54
- require 'neo4j/jars/ha/neo4j-com-1.5.jar'
55
- require 'neo4j/jars/ha/neo4j-ha-1.5.jar'
53
+ require 'neo4j/jars/ha/neo4j-backup-1.6.M01.jar'
54
+ require 'neo4j/jars/ha/neo4j-com-1.6.M01.jar'
55
+ require 'neo4j/jars/ha/neo4j-ha-1.6.M01.jar'
56
56
  require 'neo4j/jars/ha/log4j-1.2.16.jar'
57
57
  require 'neo4j/jars/ha/org.apache.servicemix.bundles.netty-3.2.5.Final_1.jar'
58
58
  require 'neo4j/jars/ha/slf4j-api-1.6.1.jar'
@@ -1,7 +1,7 @@
1
1
  # external neo4j dependencies
2
2
  require 'neo4j/to_java'
3
- require 'neo4j/jars/core/neo4j-graph-algo-1.5.jar'
4
- require 'neo4j/jars/core/neo4j-graph-matching-1.5.jar'
3
+ require 'neo4j/jars/core/neo4j-graph-algo-1.6.M01.jar'
4
+ require 'neo4j/jars/core/neo4j-graph-matching-1.6.M01.jar'
5
5
 
6
6
  module Neo4j
7
7
 
@@ -106,7 +106,7 @@ module Neo4j
106
106
  # Returns true if the neo4j db was started in read only mode.
107
107
  # This can occur if the database was locked (it was already one instance running).
108
108
  def read_only?
109
- @graph.isReadOnly
109
+ @graph.java_class == org.neo4j.kernel.EmbeddedGraphDatabase
110
110
  end
111
111
 
112
112
  # check if the database is locked. A neo4j database is locked when the database is running.
@@ -63,7 +63,7 @@ module Neo4j
63
63
  def java_dir
64
64
  dir_to_java(@dir)
65
65
  end
66
-
66
+
67
67
  def each_node(node, &block) #:nodoc:
68
68
  node._java_node.getRelationships(java_rel_type, java_dir).each do |rel|
69
69
  block.call(rel.getOtherNode(node).wrapper)
@@ -194,12 +194,7 @@ module Neo4j
194
194
  # handle specified (prefixed) relationship, e.g. has_n(:known_by).from(clazz, :type)
195
195
  @rel_type = "#{@target_class}##{args[1]}"
196
196
  @target_class = args[0]
197
- other_class_dsl = @target_class._decl_rels[args[1]]
198
- if other_class_dsl
199
- @relationship = other_class_dsl.relationship_class
200
- else
201
- Neo4j.logger.warn "Unknown outgoing relationship #{args[1]} on #{@target_class}"
202
- end
197
+ @relationship_name = args[1]
203
198
  elsif (Symbol === args[0])
204
199
  # handle unspecified (unprefixed) relationship, e.g. has_n(:known_by).from(:type)
205
200
  @rel_type = args[0]
@@ -235,7 +230,15 @@ module Neo4j
235
230
  end
236
231
 
237
232
  def relationship_class # :nodoc:
238
- @relationship
233
+ if !@relationship_name.nil? && @relationship.nil?
234
+ other_class_dsl = @target_class._decl_rels[@relationship_name]
235
+ if other_class_dsl
236
+ @relationship = other_class_dsl.relationship_class
237
+ else
238
+ Neo4j.logger.warn "Unknown outgoing relationship #{@relationship_name} on #{@target_class}"
239
+ end
240
+ end
241
+ @relationship
239
242
  end
240
243
  end
241
244
  end
@@ -1,6 +1,3 @@
1
- # https://github.com/rails/rails/blob/master/activerecord/lib/active_record/identity_map.rb
2
- # https://github.com/rails/rails/pull/76
3
-
4
1
  module Neo4j
5
2
 
6
3
  # = Neo4j Identity Map
@@ -38,7 +38,7 @@ module Neo4j
38
38
  class LuceneQuery
39
39
  include Enumerable
40
40
  include WillPaginate::Finders::Base
41
- attr_accessor :left_and_query, :left_or_query
41
+ attr_accessor :left_and_query, :left_or_query, :right_not_query
42
42
 
43
43
  def initialize(index, decl_props, query, params={})
44
44
  @index = index
@@ -156,9 +156,33 @@ module Neo4j
156
156
  # Person.find(:name=>'kalle').and(:age => 3)
157
157
  #
158
158
  def and(query2)
159
- new_query = LuceneQuery.new(@index, @decl_props, query2)
160
- new_query.left_and_query = self
161
- new_query
159
+ LuceneQuery.new(@index, @decl_props, query2).tap { |new_query| new_query.left_and_query = self }
160
+ end
161
+
162
+ # Create an OR lucene query.
163
+ #
164
+ # ==== Parameters
165
+ # query2 :: the query that should be OR together
166
+ #
167
+ # ==== Example
168
+ #
169
+ # Person.find(:name=>'kalle').or(:age => 3)
170
+ #
171
+ def or(query2)
172
+ LuceneQuery.new(@index, @decl_props, query2).tap { |new_query| new_query.left_or_query = self }
173
+ end
174
+
175
+ # Create a NOT lucene query.
176
+ #
177
+ # ==== Parameters
178
+ # query2 :: the query that should exclude matching results
179
+ #
180
+ # ==== Example
181
+ #
182
+ # Person.find(:age => 3).not(:name=>'kalle')
183
+ #
184
+ def not(query2)
185
+ LuceneQuery.new(@index, @decl_props, query2).tap { |new_query| new_query.right_not_query = self }
162
186
  end
163
187
 
164
188
 
@@ -175,11 +199,26 @@ module Neo4j
175
199
  end
176
200
 
177
201
  def build_and_query(query) #:nodoc:
178
- left_query = @left_and_query.build_query
179
- and_query = org.apache.lucene.search.BooleanQuery.new
180
- and_query.add(left_query, org.apache.lucene.search.BooleanClause::Occur::MUST)
181
- and_query.add(query, org.apache.lucene.search.BooleanClause::Occur::MUST)
182
- and_query
202
+ build_composite_query(@left_and_query.build_query, query, org.apache.lucene.search.BooleanClause::Occur::MUST)
203
+ end
204
+
205
+ def build_or_query(query) #:nodoc:
206
+ build_composite_query(@left_or_query.build_query, query, org.apache.lucene.search.BooleanClause::Occur::SHOULD)
207
+ end
208
+
209
+ def build_not_query(query) #:nodoc:
210
+ right_query = @right_not_query.build_query
211
+ composite_query = org.apache.lucene.search.BooleanQuery.new
212
+ composite_query.add(query, org.apache.lucene.search.BooleanClause::Occur::MUST_NOT)
213
+ composite_query.add(right_query, org.apache.lucene.search.BooleanClause::Occur::MUST)
214
+ composite_query
215
+ end
216
+
217
+ def build_composite_query(left_query, right_query, opeartor) #:nodoc:
218
+ composite_query = org.apache.lucene.search.BooleanQuery.new
219
+ composite_query.add(left_query, opeartor)
220
+ composite_query.add(right_query, opeartor)
221
+ composite_query
183
222
  end
184
223
 
185
224
  def build_sort_query(query) #:nodoc:
@@ -224,6 +263,8 @@ module Neo4j
224
263
  query = @query
225
264
  query = build_hash_query(query) if Hash === query
226
265
  query = build_and_query(query) if @left_and_query
266
+ query = build_or_query(query) if @left_or_query
267
+ query = build_not_query(query) if @right_not_query
227
268
  query = build_sort_query(query) if @order
228
269
  query
229
270
  end
@@ -0,0 +1,66 @@
1
+ module Neo4j::Rails
2
+ # Allows accepting id for association objjects. For example
3
+ # class Book < Neo4j::Model
4
+ # has_one(:author).to(Author)
5
+ # accepts_id_for :author
6
+ # end
7
+ #
8
+ # This would add a author_id getter and setter on Book. You could use
9
+ # book = Book.new(:name => 'Graph DBs', :author_id => 11)
10
+ # book.author_id # 11
11
+ # book.author_id = 13
12
+ # TODO: Support for has_n associations
13
+ module AcceptId
14
+ extend ActiveSupport::Concern
15
+
16
+ module ClassMethods
17
+ # Adds association_id getter and setter for one or more has_one associations
18
+ #
19
+ # @example
20
+ # class Book < Neo4j::Model
21
+ # has_one(:author).to(Author)
22
+ # has_one(:publisher).to(Publisher)
23
+ # accepts_id_for :author, :publisher
24
+ # end
25
+ def accepts_id_for(*association_names)
26
+ association_names.each do |association_name|
27
+ define_association_id_getter(association_name)
28
+ define_association_id_setter(association_name)
29
+ accepts_id_associations << association_name
30
+ end
31
+ end
32
+
33
+ # Check if model accepsts id for its association
34
+ # @example
35
+ # Book.accepts_id_for?(:author) => true
36
+ # Book.accepts_id_for?(:genre) => false
37
+ def accepts_id_for?(association_name)
38
+ accepts_id_associations.include?(association_name)
39
+ end
40
+
41
+ def accepts_id_associations #nodoc
42
+ @accepts_id_associations ||= []
43
+ end
44
+
45
+ protected
46
+ def define_association_id_getter(association_name)
47
+ class_eval %Q{
48
+ def #{association_name}_id
49
+ association_object = self.#{association_name}
50
+ association_object.present? ? association_object.id : nil
51
+ end
52
+ }, __FILE__, __LINE__
53
+ end
54
+
55
+ def define_association_id_setter(association_name)
56
+ class_eval %Q{
57
+ def #{association_name}_id=(id)
58
+ relation_target_class = self.class._decl_rels[:#{association_name}].target_class
59
+ association_class = relation_target_class <= self.class ? Neo4j::Model : relation_target_class
60
+ self.#{association_name} = id.present? ? association_class.find(id) : nil
61
+ end
62
+ }, __FILE__, __LINE__
63
+ end
64
+ end
65
+ end
66
+ end
@@ -55,8 +55,7 @@ module Neo4j
55
55
  def #{rel_type}=(other)
56
56
  dsl = _decl_rels_for(:'#{rel_type}')
57
57
  storage = _create_or_get_storage_for_decl_rels(dsl)
58
- rel = storage.single_relationship(dsl.dir)
59
- rel && rel.destroy
58
+ storage.destroy_single_relationship(dsl.dir)
60
59
  storage.create_relationship_to(other, dsl.dir)
61
60
  end
62
61
  RUBY
@@ -270,6 +270,7 @@ module Neo4j
270
270
  include Finders # ActiveRecord style find
271
271
  include Relationships # for none persisted relationships
272
272
  include Compositions
273
+ include AcceptId
273
274
  end
274
275
  end
275
276
  end
@@ -1,3 +1,5 @@
1
+ require 'active_support/core_ext/class/attribute_accessors'
2
+
1
3
  module Neo4j
2
4
  module Rails
3
5
  # Observer classes respond to life cycle callbacks to implement trigger-like
@@ -86,11 +88,26 @@ module Neo4j
86
88
  # In order to activate an observer, list it in the +config.neo4j.observers+
87
89
  # configuration setting in your +config/application.rb+ file.
88
90
  #
89
- # config.neo4j.observers = :comment_observer, :signup_observer
91
+ # config.neo4j.observers = [:comment_observer, :signup_observer]
90
92
  #
91
93
  # Observers will not be invoked unless you define them in your
92
94
  # application configuration.
93
95
  #
96
+ # During testing you may want (and probably should) to disable all the observers.
97
+ # Most of the time you don't want any kind of emails to be sent when creating objects.
98
+ # This should improve the speed of your tests and isolate the models and observer logic.
99
+ #
100
+ # For example, the following will disable the observers in RSpec:
101
+ #
102
+ # config.before(:each) { Neo4j::Rails::Observer.disable_observers }
103
+ #
104
+ # But if you do want to run a particular observer(s) as part of the test,
105
+ # you can temporarily enable it:
106
+ #
107
+ # Neo4j::Rails::Observer.with_observers(:user_recorder, :account_observer) do
108
+ # # Any code here will work with observers enabled
109
+ # end
110
+ #
94
111
  # == Loading
95
112
  #
96
113
  # Observers register themselves with the model class that they observe,
@@ -113,6 +130,48 @@ module Neo4j
113
130
  super and observed_descendants.each { |klass| add_observer!(klass) }
114
131
  end
115
132
 
133
+ cattr_accessor :default_observers_enabled, :observers_enabled
134
+
135
+ # TODO: Add docs
136
+ class << self
137
+ # Enables all observers (default behavior)
138
+ def enable_observers
139
+ self.default_observers_enabled = true
140
+ end
141
+
142
+ # Disables all observers
143
+ def disable_observers
144
+ self.default_observers_enabled = false
145
+ end
146
+
147
+ # Run a block with a specific set of observers enabled
148
+ def with_observers(*observer_syms)
149
+ self.observers_enabled = Array(observer_syms).map do |o|
150
+ o.respond_to?(:instance) ? o.instance : o.to_s.classify.constantize.instance
151
+ end
152
+ yield
153
+ ensure
154
+ self.observers_enabled = []
155
+ end
156
+
157
+ # Determines whether an observer is enabled. Either:
158
+ # - All observers are enabled OR
159
+ # - The observer is in the whitelist
160
+ def observer_enabled?(observer)
161
+ default_observers_enabled or self.observers_enabled.include?(observer)
162
+ end
163
+ end
164
+
165
+
166
+ # Determines whether this observer should be run
167
+ def observer_enabled?
168
+ self.class.observer_enabled?(self)
169
+ end
170
+
171
+ # By default, enable all observers
172
+ enable_observers
173
+ self.observers_enabled = []
174
+
116
175
  protected
117
176
 
118
177
  # Get all the child observers.
@@ -149,7 +208,7 @@ module Neo4j
149
208
  callback_meth = :"_notify_#{observer_name}_for_#{callback}"
150
209
  unless klass.respond_to?(callback_meth)
151
210
  klass.send(:define_method, callback_meth) do |&block|
152
- observer.send(callback, self, &block)
211
+ observer.send(callback, self, &block) if observer.observer_enabled?
153
212
  end
154
213
  klass.send(callback, callback_meth)
155
214
  end
@@ -190,7 +190,7 @@ module Neo4j
190
190
  # Ensure any defaults are stored in the DB
191
191
  def write_default_attributes
192
192
  attribute_defaults.each do |attribute, value|
193
- write_attribute(attribute, Neo4j::TypeConverters.convert(value, attribute, self.class)) unless changed_attributes.has_key?(attribute) || _java_node.has_property?(attribute)
193
+ write_attribute(attribute, Neo4j::TypeConverters.convert(value, attribute, self.class, false)) unless changed_attributes.has_key?(attribute) || _java_node.has_property?(attribute)
194
194
  end
195
195
  end
196
196
 
@@ -11,6 +11,7 @@ require 'neo4j/rails/validations'
11
11
  require 'neo4j/rails/callbacks'
12
12
  require 'neo4j/rails/observer'
13
13
  require 'neo4j/rails/compositions'
14
+ require 'neo4j/rails/accept_id'
14
15
  require 'neo4j/rails/timestamps'
15
16
  require 'neo4j/rails/serialization'
16
17
  require 'neo4j/rails/attributes'
@@ -151,16 +151,19 @@ module Neo4j
151
151
  def create()
152
152
  begin
153
153
  # prevent calling create twice
154
- @start_node.rm_outgoing_rel(type, self)
155
- @end_node.rm_incoming_rel(type, self)
154
+ @start_node.add_unpersisted_outgoing_rel(type, self)
155
+ @end_node.add_unpersisted_incoming_rel(type, self)
156
156
 
157
- _persist_start_node
158
- _persist_end_node
157
+ return unless _persist_start_node && _persist_end_node
159
158
 
160
159
  @_java_rel = Neo4j::Relationship.new(type, start_node, end_node)
161
160
  Neo4j::IdentityMap.add(@_java_rel, self)
162
161
  init_on_create
163
162
  clear_changes
163
+
164
+ @start_node.rm_unpersisted_outgoing_rel(type, self)
165
+ @end_node.rm_unpersisted_incoming_rel(type, self)
166
+
164
167
  end unless @end_node.nil? or @start_node.nil?
165
168
  true
166
169
  end
@@ -170,18 +173,14 @@ module Neo4j
170
173
  end
171
174
 
172
175
  def _persist_start_node
173
- unless @start_node.persisted? || @start_node.save
174
- # not sure if this can happen - probably a bug
175
- raise "Can't save start_node #{@start_node} id #{@start_node.id}"
176
- end
176
+ (!@start_node.persisted? || @start_node.relationships_changed?) ? @start_node.save : true
177
177
  end
178
178
 
179
179
  def _persist_end_node
180
- unless @end_node.persisted? || @end_node.save
181
- raise "Can't save end_node #{@end_node} id #{@end_node.id}"
182
- end
180
+ (!@end_node.persisted? || @end_node.relationships_changed?) ? @end_node.save : true
183
181
  end
184
182
 
183
+
185
184
  def init_on_create(*)
186
185
  #self["_classname"] = self.class.to_s
187
186
  write_default_attributes
@@ -185,7 +185,11 @@ module Neo4j
185
185
  def to_s
186
186
  "Node dir: #{@dir}, #{@storage}"
187
187
  end
188
-
188
+
189
+ def rel_changed?
190
+ @storage.persisted?
191
+ end
192
+
189
193
  protected
190
194
 
191
195
 
@@ -30,6 +30,9 @@ module Neo4j
30
30
  @_relationships[decl_rels.rel_type.to_sym] ||= Storage.new(self, decl_rels.rel_type, decl_rels)
31
31
  end
32
32
 
33
+ def _storage_for(rel_type) #:nodoc:
34
+ @_relationships[rel_type.to_sym]
35
+ end
33
36
 
34
37
  # If the node is persisted and it does not have any unsaved relationship it returns a Neo4j::NodeTraverser.
35
38
  # Otherwise it will return a NodesDSL which behaves like the Neo4j::NodeTraverser except that it does not
@@ -90,6 +93,37 @@ module Neo4j
90
93
  _create_or_get_storage(rel_type).rm_outgoing_rel(rel)
91
94
  end
92
95
 
96
+ def rm_outgoing_rel(rel_type, rel) #:nodoc:
97
+ _create_or_get_storage(rel_type).rm_outgoing_rel(rel)
98
+ end
99
+
100
+ def add_unpersisted_incoming_rel(rel_type, rel) #:nodoc
101
+ storage = _storage_for(rel_type)
102
+ # move the relationship since we are now about to store the relationship
103
+ storage.add_unpersisted_incoming_rel(rel)
104
+ storage.rm_incoming_rel(rel)
105
+ end
106
+
107
+ def add_unpersisted_outgoing_rel(rel_type, rel) #:nodoc
108
+ storage = _storage_for(rel_type)
109
+ # move the relationship since we are now about to store the relationship
110
+ storage.add_unpersisted_outgoing_rel(rel)
111
+ storage.rm_outgoing_rel(rel)
112
+ end
113
+
114
+ def rm_unpersisted_outgoing_rel(rel_type, rel) #:nodoc
115
+ if (storage = _storage_for(rel_type))
116
+ storage.rm_unpersisted_outgoing_rel(rel)
117
+ end
118
+ end
119
+
120
+ def rm_unpersisted_incoming_rel(rel_type, rel) #:nodoc
121
+ if (storage = _storage_for(rel_type))
122
+ storage.rm_unpersisted_incoming_rel(rel)
123
+ end
124
+ end
125
+
126
+
93
127
  end
94
128
  end
95
129
  end
@@ -20,17 +20,21 @@ module Neo4j
20
20
  end
21
21
 
22
22
  def to_s #:nodoc:
23
- "Storage #{object_id} node: #{@node.id} rel_type: #{@rel_type} outgoing #{@outgoing_rels.size} incoming #{@incoming_rels.size}"
23
+ "Storage #{object_id} node: #{@node.id} rel_type: #{@rel_type} outgoing #{@outgoing_rels.size}/#{@unpersisted_outgoing_rels && @unpersisted_outgoing_rels.size} incoming #{@incoming_rels.size}/#{@unpersisted_incoming_rels && @unpersisted_incoming_rels.size}"
24
24
  end
25
25
 
26
26
  def clear_unpersisted
27
27
  @outgoing_rels.clear
28
28
  @incoming_rels.clear
29
+ @unpersisted_outgoing_rels = nil
30
+ @unpersisted_incoming_rels = nil
29
31
  end
30
32
 
31
33
  def remove_from_identity_map
32
34
  @outgoing_rels.each {|r| Neo4j::IdentityMap.remove(r._java_rel)}
33
35
  @incoming_rels.each {|r| Neo4j::IdentityMap.remove(r._java_rel)}
36
+ @unpersisted_outgoing_rels = nil
37
+ @unpersisted_incoming_rels = nil
34
38
  end
35
39
 
36
40
  def size(dir)
@@ -57,9 +61,9 @@ module Neo4j
57
61
  def relationships(dir)
58
62
  case dir
59
63
  when :outgoing
60
- @outgoing_rels
64
+ @unpersisted_outgoing_rels || @outgoing_rels
61
65
  when :incoming
62
- @incoming_rels
66
+ @unpersisted_incoming_rels || @incoming_rels
63
67
  when :both
64
68
  @incoming_rels + @outgoing_rels
65
69
  end
@@ -122,6 +126,11 @@ module Neo4j
122
126
  end
123
127
  end
124
128
 
129
+ def destroy_single_relationship(dir)
130
+ rel = single_relationship(dir)
131
+ rel && rel.destroy && relationships(dir).delete(rel)
132
+ end
133
+
125
134
  def all_relationships(dir)
126
135
  Enumerator.new(self, :each_rel, dir)
127
136
  end
@@ -155,6 +164,18 @@ module Neo4j
155
164
  @outgoing_rels << rel
156
165
  end
157
166
 
167
+ # Makes the given relationship available in callbacks
168
+ def add_unpersisted_incoming_rel(rel)
169
+ @unpersisted_incoming_rels ||= []
170
+ @unpersisted_incoming_rels << rel
171
+ end
172
+
173
+ # Makes the given relationship available in callbacks
174
+ def add_unpersisted_outgoing_rel(rel)
175
+ @unpersisted_outgoing_rels ||= []
176
+ @unpersisted_outgoing_rels << rel
177
+ end
178
+
158
179
  def rm_incoming_rel(rel)
159
180
  @incoming_rels.delete(rel)
160
181
  end
@@ -163,6 +184,16 @@ module Neo4j
163
184
  @outgoing_rels.delete(rel)
164
185
  end
165
186
 
187
+ def rm_unpersisted_incoming_rel(rel)
188
+ @unpersisted_incoming_rels.delete(rel)
189
+ @unpersisted_incoming_rels = nil if @unpersisted_incoming_rels.empty?
190
+ end
191
+
192
+ def rm_unpersisted_outgoing_rel(rel)
193
+ @unpersisted_outgoing_rels.delete(rel)
194
+ @unpersisted_outgoing_rels = nil if @unpersisted_outgoing_rels.empty?
195
+ end
196
+
166
197
  def persisted?
167
198
  @outgoing_rels.empty? && @incoming_rels.empty?
168
199
  end
@@ -174,14 +205,12 @@ module Neo4j
174
205
  [@outgoing_rels, @incoming_rels, @persisted_related_nodes, @persisted_node_to_relationships, @persisted_relationships].each{|c| c.clear}
175
206
 
176
207
  out_rels.each do |rel|
177
- rel.end_node.rm_incoming_rel(@rel_type.to_sym, rel) if rel.end_node
178
208
  success = rel.persisted? || rel.save
179
209
  # don't think this can happen - just in case, TODO
180
210
  raise "Can't save outgoing #{rel}, validation errors ? #{rel.errors.inspect}" unless success
181
211
  end
182
212
 
183
213
  in_rels.each do |rel|
184
- rel.start_node.rm_outgoing_rel(@rel_type.to_sym, rel) if rel.start_node
185
214
  success = rel.persisted? || rel.save
186
215
  # don't think this can happen - just in case, TODO
187
216
  raise "Can't save incoming #{rel}, validation errors ? #{rel.errors.inspect}" unless success
@@ -68,6 +68,46 @@ module Neo4j
68
68
  end
69
69
  end
70
70
 
71
+ class SymbolConverter
72
+ class << self
73
+
74
+ def convert?(class_or_symbol)
75
+ :symbol == class_or_symbol || Symbol == class_or_symbol
76
+ end
77
+
78
+ def to_java(value)
79
+ return nil unless value
80
+ value.to_s
81
+ end
82
+
83
+ def to_ruby(value)
84
+ return nil unless value
85
+ value.to_sym
86
+ end
87
+ end
88
+ end
89
+
90
+
91
+ class StringConverter
92
+ class << self
93
+
94
+ def convert?(class_or_symbol)
95
+ [String, :string, :text].include? class_or_symbol
96
+ end
97
+
98
+ def to_java(value)
99
+ return nil unless value
100
+ value.to_s
101
+ end
102
+
103
+ def to_ruby(value)
104
+ return nil unless value
105
+ value.to_s
106
+ end
107
+ end
108
+ end
109
+
110
+
71
111
 
72
112
  class FixnumConverter
73
113
  class << self
@@ -184,7 +224,10 @@ module Neo4j
184
224
  end
185
225
 
186
226
  # Always returns a converter that handles to_ruby or to_java
187
- def converter(type = nil)
227
+ # if +enforce_type+ is set to false then it will raise in case of unknown type
228
+ # otherwise it will return the DevaultConverter.
229
+ def converter(type = nil, enforce_type = true)
230
+ return DefaultConverter unless type
188
231
  @converters ||= begin
189
232
  Neo4j::TypeConverters.constants.find_all do |c|
190
233
  Neo4j::TypeConverters.const_get(c).respond_to?(:convert?)
@@ -192,14 +235,16 @@ module Neo4j
192
235
  Neo4j::TypeConverters.const_get(c)
193
236
  end
194
237
  end
195
- (type && @converters.find { |c| c.convert?(type) }) || DefaultConverter
238
+ found = @converters.find {|c| c.convert?(type) }
239
+ raise "The type #{type.inspect} is unknown. Use one of #{@converters.map{|c| c.name.demodulize.sub('Converter','') }.join(", ")} or create a custom type converter." if !found && enforce_type
240
+ found or DefaultConverter
196
241
  end
197
242
 
198
243
  # Converts the given value to a Java type by using the registered converters.
199
244
  # It just looks at the class of the given value unless an attribute name is given.
200
245
  # It will convert it if there is a converter registered (in Neo4j::Config) for this value.
201
- def convert(value, attribute = nil, klass = nil)
202
- converter(attribute_type(value, attribute, klass)).to_java(value)
246
+ def convert(value, attribute = nil, klass = nil, enforce_type = true)
247
+ converter(attribute_type(value, attribute, klass), enforce_type).to_java(value)
203
248
  end
204
249
 
205
250
  # Converts the given property (key, value) to Java if there is a type converter for given type.
data/lib/neo4j/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Neo4j
2
- VERSION = "1.3.0"
2
+ VERSION = "1.3.1"
3
3
  end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: neo4j
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 1.3.0
5
+ version: 1.3.1
6
6
  platform: java
7
7
  authors:
8
8
  - Andreas Ronge
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-12-06 00:00:00 Z
13
+ date: 2011-12-14 00:00:00 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: orm_adapter
@@ -137,6 +137,7 @@ files:
137
137
  - lib/neo4j/rails/timestamps.rb
138
138
  - lib/neo4j/rails/callbacks.rb
139
139
  - lib/neo4j/rails/tx_methods.rb
140
+ - lib/neo4j/rails/accept_id.rb
140
141
  - lib/neo4j/rails/rel_persistence.rb
141
142
  - lib/neo4j/rails/finders.rb
142
143
  - lib/neo4j/rails/relationship.rb
@@ -150,29 +151,30 @@ files:
150
151
  - lib/neo4j/rails/validations/associated.rb
151
152
  - lib/neo4j/rails/validations/uniqueness.rb
152
153
  - lib/neo4j/rails/validations/non_nil.rb
153
- - lib/neo4j/jars/core/neo4j-kernel-1.5.jar
154
- - lib/neo4j/jars/core/server-api-1.5.jar
154
+ - lib/neo4j/jars/neo4j-community-1.6.M01.jar
155
+ - lib/neo4j/jars/core/neo4j-graph-matching-1.6.M01.jar
156
+ - lib/neo4j/jars/core/neo4j-community-1.6.M01.jar
157
+ - lib/neo4j/jars/core/neo4j-kernel-1.6.M01.jar
158
+ - lib/neo4j/jars/core/server-api-1.6.M01.jar
155
159
  - lib/neo4j/jars/core/geronimo-jta_1.1_spec-1.1.1.jar
156
- - lib/neo4j/jars/core/neo4j-graph-matching-1.5.jar
157
- - lib/neo4j/jars/core/neo4j-shell-1.5.jar
158
- - lib/neo4j/jars/core/neo4j-lucene-index-1.5.jar
160
+ - lib/neo4j/jars/core/neo4j-lucene-index-1.6.M01.jar
161
+ - lib/neo4j/jars/core/neo4j-jmx-1.6.M01.jar
159
162
  - lib/neo4j/jars/core/scala-library-2.9.0-1.jar
163
+ - lib/neo4j/jars/core/neo4j-cypher-1.6.M01.jar
160
164
  - lib/neo4j/jars/core/lucene-core-3.1.0.jar
161
- - lib/neo4j/jars/core/neo4j-graph-algo-1.5.jar
162
- - lib/neo4j/jars/core/neo4j-udc-1.5.jar
163
- - lib/neo4j/jars/core/neo4j-community-1.5.jar
164
- - lib/neo4j/jars/core/neo4j-cypher-1.5.jar
165
+ - lib/neo4j/jars/core/neo4j-graph-algo-1.6.M01.jar
165
166
  - lib/neo4j/jars/core/org.apache.servicemix.bundles.jline-0.9.94_1.jar
166
- - lib/neo4j/jars/core/neo4j-jmx-1.5.jar
167
- - lib/neo4j/jars/ha/neo4j-ha-1.5.jar
167
+ - lib/neo4j/jars/core/neo4j-shell-1.6.M01.jar
168
+ - lib/neo4j/jars/core/neo4j-udc-1.6.M01.jar
168
169
  - lib/neo4j/jars/ha/slf4j-api-1.6.1.jar
169
- - lib/neo4j/jars/ha/neo4j-management-1.5.jar
170
- - lib/neo4j/jars/ha/neo4j-com-1.5.jar
171
- - lib/neo4j/jars/ha/neo4j-enterprise-1.5.jar
170
+ - lib/neo4j/jars/ha/neo4j-backup-1.6.M01.jar
172
171
  - lib/neo4j/jars/ha/zookeeper-3.3.2.jar
173
172
  - lib/neo4j/jars/ha/org.apache.servicemix.bundles.netty-3.2.5.Final_1.jar
174
173
  - lib/neo4j/jars/ha/log4j-1.2.16.jar
175
- - lib/neo4j/jars/ha/neo4j-backup-1.5.jar
174
+ - lib/neo4j/jars/ha/neo4j-enterprise-1.6.M01.jar
175
+ - lib/neo4j/jars/ha/neo4j-ha-1.6.M01.jar
176
+ - lib/neo4j/jars/ha/neo4j-management-1.6.M01.jar
177
+ - lib/neo4j/jars/ha/neo4j-com-1.6.M01.jar
176
178
  - lib/neo4j/index/indexer.rb
177
179
  - lib/neo4j/index/lucene_query.rb
178
180
  - lib/neo4j/index/indexer_registry.rb
Binary file