neo4j 2.0.0.alpha.5-java → 2.0.0.alpha.6-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. data/CHANGELOG +12 -0
  2. data/Gemfile +0 -4
  3. data/README.rdoc +106 -62
  4. data/lib/neo4j.rb +7 -33
  5. data/lib/neo4j/performance.rb +43 -0
  6. data/lib/neo4j/rails/accept_id.rb +19 -18
  7. data/lib/neo4j/rails/attributes.rb +366 -120
  8. data/lib/neo4j/rails/finders.rb +41 -15
  9. data/lib/neo4j/rails/has_n.rb +203 -0
  10. data/lib/neo4j/rails/identity.rb +25 -0
  11. data/lib/neo4j/rails/model.rb +65 -242
  12. data/lib/neo4j/rails/nested_attributes.rb +108 -0
  13. data/lib/neo4j/rails/node_persistance.rb +56 -0
  14. data/lib/neo4j/rails/observer.rb +0 -2
  15. data/lib/neo4j/rails/persistence.rb +32 -154
  16. data/lib/neo4j/rails/rack_middleware.rb +26 -2
  17. data/lib/neo4j/rails/rails.rb +9 -6
  18. data/lib/neo4j/rails/railtie.rb +1 -2
  19. data/lib/neo4j/rails/relationship.rb +18 -125
  20. data/lib/neo4j/rails/relationship_persistence.rb +107 -0
  21. data/lib/neo4j/rails/relationships/node_dsl.rb +72 -44
  22. data/lib/neo4j/rails/relationships/relationships.rb +187 -59
  23. data/lib/neo4j/rails/relationships/rels_dsl.rb +18 -17
  24. data/lib/neo4j/rails/relationships/storage.rb +19 -17
  25. data/lib/neo4j/rails/timestamps.rb +53 -51
  26. data/lib/neo4j/rails/transaction.rb +9 -1
  27. data/lib/neo4j/rails/validations/uniqueness.rb +1 -1
  28. data/lib/neo4j/rails/versioning/versioning.rb +2 -2
  29. data/lib/neo4j/version.rb +1 -1
  30. data/lib/orm_adapter/adapters/neo4j.rb +47 -46
  31. data/neo4j.gemspec +1 -1
  32. metadata +10 -69
  33. data/lib/neo4j/algo/algo.rb +0 -294
  34. data/lib/neo4j/batch/batch.rb +0 -4
  35. data/lib/neo4j/batch/indexer.rb +0 -109
  36. data/lib/neo4j/batch/inserter.rb +0 -179
  37. data/lib/neo4j/batch/rule_inserter.rb +0 -24
  38. data/lib/neo4j/batch/rule_node.rb +0 -72
  39. data/lib/neo4j/config.rb +0 -177
  40. data/lib/neo4j/core_ext/class/inheritable_attributes.rb +0 -12
  41. data/lib/neo4j/core_ext/class/rewrite_inheritable_attributes.rb +0 -170
  42. data/lib/neo4j/database.rb +0 -158
  43. data/lib/neo4j/equal.rb +0 -21
  44. data/lib/neo4j/event_handler.rb +0 -263
  45. data/lib/neo4j/has_list/class_methods.rb +0 -11
  46. data/lib/neo4j/has_list/has_list.rb +0 -3
  47. data/lib/neo4j/has_list/mapping.rb +0 -133
  48. data/lib/neo4j/has_n/class_methods.rb +0 -119
  49. data/lib/neo4j/has_n/decl_relationship_dsl.rb +0 -246
  50. data/lib/neo4j/has_n/has_n.rb +0 -3
  51. data/lib/neo4j/has_n/mapping.rb +0 -98
  52. data/lib/neo4j/identity_map.rb +0 -140
  53. data/lib/neo4j/index/class_methods.rb +0 -108
  54. data/lib/neo4j/index/index.rb +0 -39
  55. data/lib/neo4j/index/indexer.rb +0 -341
  56. data/lib/neo4j/index/indexer_registry.rb +0 -68
  57. data/lib/neo4j/index/lucene_query.rb +0 -256
  58. data/lib/neo4j/load.rb +0 -25
  59. data/lib/neo4j/migrations/class_methods.rb +0 -110
  60. data/lib/neo4j/migrations/extensions.rb +0 -58
  61. data/lib/neo4j/migrations/lazy_node_mixin.rb +0 -41
  62. data/lib/neo4j/migrations/migration.rb +0 -112
  63. data/lib/neo4j/migrations/migrations.rb +0 -6
  64. data/lib/neo4j/migrations/node_mixin.rb +0 -80
  65. data/lib/neo4j/migrations/ref_node_wrapper.rb +0 -32
  66. data/lib/neo4j/model.rb +0 -4
  67. data/lib/neo4j/neo4j.rb +0 -216
  68. data/lib/neo4j/node.rb +0 -270
  69. data/lib/neo4j/node_mixin/class_methods.rb +0 -51
  70. data/lib/neo4j/node_mixin/node_mixin.rb +0 -141
  71. data/lib/neo4j/paginated.rb +0 -23
  72. data/lib/neo4j/property/class_methods.rb +0 -79
  73. data/lib/neo4j/property/property.rb +0 -111
  74. data/lib/neo4j/rails/mapping/property.rb +0 -183
  75. data/lib/neo4j/rails/rel_persistence.rb +0 -237
  76. data/lib/neo4j/relationship.rb +0 -239
  77. data/lib/neo4j/relationship_mixin/class_methods.rb +0 -36
  78. data/lib/neo4j/relationship_mixin/relationship_mixin.rb +0 -142
  79. data/lib/neo4j/relationship_set.rb +0 -58
  80. data/lib/neo4j/rels/rels.rb +0 -110
  81. data/lib/neo4j/rels/traverser.rb +0 -102
  82. data/lib/neo4j/rule/class_methods.rb +0 -201
  83. data/lib/neo4j/rule/event_listener.rb +0 -66
  84. data/lib/neo4j/rule/functions/count.rb +0 -43
  85. data/lib/neo4j/rule/functions/function.rb +0 -74
  86. data/lib/neo4j/rule/functions/functions.rb +0 -3
  87. data/lib/neo4j/rule/functions/sum.rb +0 -29
  88. data/lib/neo4j/rule/rule.rb +0 -150
  89. data/lib/neo4j/rule/rule_node.rb +0 -217
  90. data/lib/neo4j/to_java.rb +0 -31
  91. data/lib/neo4j/transaction.rb +0 -73
  92. data/lib/neo4j/traversal/filter_predicate.rb +0 -25
  93. data/lib/neo4j/traversal/prune_evaluator.rb +0 -14
  94. data/lib/neo4j/traversal/rel_expander.rb +0 -31
  95. data/lib/neo4j/traversal/traversal.rb +0 -141
  96. data/lib/neo4j/traversal/traverser.rb +0 -284
  97. data/lib/neo4j/type_converters/type_converters.rb +0 -288
data/CHANGELOG CHANGED
@@ -1,3 +1,15 @@
1
+ == 2.0.0.alpha.6 / 2012-04-15
2
+ * Complete rewrite and smaller change of API + lots of refactoring and better RSpecs
3
+ * Moved code to the neo4j-core and neo4j-wrapper gems
4
+ * Changed API - index properties using the Neo4j::Rails::Model (property :name, :index => :exact)
5
+ * Changed API - rel_type always returns a Symbol
6
+ * Changed API - #rels and #rel first parameter is always :outgoing, :incoming or :both
7
+ * Cypher DSL support, see neo4j-core
8
+ * Made the Lucene indexing more flexible
9
+ * Renamed size methods to count since it does simply count all the relationships (e.g. Person.all.count)
10
+ * Modularization - e.g. make it possible to create your own wrapper
11
+ * Added builder method for has_one relationships (just like ActiveRecord build_best_friend)
12
+
1
13
  == 2.0.0.alpha.5 / 2012-03-27
2
14
  * Fix for HA/cluster bug [#173]
3
15
  * Upgrade to neo4j-community jars 1.7.0.alpha.1
data/Gemfile CHANGED
@@ -2,9 +2,6 @@ source :gemcutter
2
2
 
3
3
  gemspec
4
4
 
5
- gem 'neo4j-advanced', "1.7.0.alpha.1", :require => false
6
- gem 'neo4j-enterprise', "1.7.0.alpha.1", :require => false
7
-
8
5
  group 'development' do
9
6
  gem 'guard'
10
7
  gem 'ruby_gntp', :require => false # GrowlNotify for Mac
@@ -12,7 +9,6 @@ group 'development' do
12
9
  gem 'rb-fsevent', :require => false
13
10
  gem 'rb-fchange', :require => false
14
11
  gem "guard-rspec"
15
- gem "horo", ">= 1.0.2" # TODO: Why horo, YARD seems to be much better option?
16
12
  #gem 'ruby-debug-base19' if RUBY_VERSION.include? "1.9"
17
13
  #gem 'ruby-debug-base' if RUBY_VERSION.include? "1.8"
18
14
  #gem "ruby-debug-ide"
data/README.rdoc CHANGED
@@ -1,4 +1,4 @@
1
- == Welcome to Neo4j.rb {<img src="https://secure.travis-ci.org/andreasronge/neo4j.png" />}[http://travis-ci.org/andreasronge/neo4j] {<img src="https://gemnasium.com/andreasronge/neo4j.png" />}[https://gemnasium.com/andreasronge/neo4j]
1
+ = Welcome to Neo4j.rb {<img src="https://secure.travis-ci.org/andreasronge/neo4j.png" />}[http://travis-ci.org/andreasronge/neo4j] {<img src="https://gemnasium.com/andreasronge/neo4j.png" />}[https://gemnasium.com/andreasronge/neo4j]
2
2
 
3
3
  Neo4j.rb is a graph database for JRuby.
4
4
 
@@ -9,25 +9,28 @@ It uses two powerful and mature Java libraries:
9
9
  * {Neo4J}[http://www.neo4j.org] - for persistence and traversal of the graph
10
10
  * {Lucene}[http://lucene.apache.org/java/docs/index.html] for querying and indexing.
11
11
 
12
- === Documentation
12
+ == Documentation
13
+
14
+ ==== Version < 2.0.alpha.5
13
15
 
14
16
  * {Guides and API}[http://neo4j.rubyforge.org/guides/index.html]
15
17
  * {RDoc}[http://neo4j.rubyforge.org]
16
18
  * {Blog: Neo4j and Rails 3}[http://blog.jayway.com/2011/03/02/neo4j-rb-1-0-0-and-rails-3/]
17
19
  * {Kvitter Example Application}[https://github.com/andreasronge/kvitter/]
18
20
 
19
- === Status of Upcomming 2.0 Release
21
+ ==== Version >= 2.0
20
22
 
21
- See the {neo4j-core gem}[https://github.com/andreasronge/neo4j-core] and GitHub issues.
23
+ * {YARD}[http://rdoc.info/github/andreasronge/neo4j/master/frames]
24
+ * RSpecs - There are 2023 RSpecs (478/neo4j-core, 425/neo4j-wrapper and 1120/this gem - 2012 April)
22
25
 
23
- Improvements:
24
- * More modular (create your own wrapper or use Neo4j::NodeMixin/Neo4j::Rails::Model)
25
- * Better performance
26
- * More consistent API
27
- * Better quality of RSpecs, code and docs (YARD)
26
+ === Presentation Materials and other URLs
28
27
 
28
+ * {JRubyConf 2012 May}[http://jrubyconf.com/#speakers]
29
+ * {Presentation: RailsConf 2011}[http://andreasronge.github.com/neo4j-railsconf.pdf]
30
+ * {Nordic Ruby 2010 May 21-23}[http://nordicruby.org/speakers#user_29]
31
+ * {Docs from NeoTechnology}[http://docs.neo4j.org/]
29
32
 
30
- === Why Neo4j.rb or a Graph Database ?
33
+ == Why Neo4j.rb or a Graph Database ?
31
34
 
32
35
  Here are some of the major benefits of Neo4j.rb
33
36
 
@@ -43,64 +46,50 @@ Here are some of the major benefits of Neo4j.rb
43
46
  * ACID Transaction with rollbacks support.
44
47
 
45
48
 
46
- === Some Examples
47
-
48
- ==== Neo4j::Node
49
+ == Public API
49
50
 
50
- Example of creating a Neo4j::Node
51
+ The neo4j gem depends on the neo4j-wrapper and neo4j-core gems.
51
52
 
52
- require "rubygems"
53
- require 'neo4j'
53
+ === neo4j gem
54
54
 
55
- Neo4j::Transaction.run do
56
- node = Neo4j::Node.new (:name => 'andreas')
57
- node.outgoing(:friends) << Neo4j::Node.new (:name => 'peter')
58
- node.outgoing(:friends).each {|node| puts "name #{node[:name]}"}
59
- end
55
+ {Neo4j::Rails::Model}
60
56
 
61
- ==== Neo4j::NodeMixin
57
+ {Neo4j::Rails::Relationship}
62
58
 
63
- Example of mapping a ruby class to a node and delaring properties and relationships and lucene index.
59
+ {Neo4j::Rails::Observer}
64
60
 
65
- class Person
66
- include Neo4j::NodeMixin
67
- property :name
68
- property :city
61
+ {Neo4j::Railtie}
69
62
 
70
- has_n :friends
71
- has_one :address
72
- index :name
73
- end
63
+ {Neo4j::Rails::Versioning}
74
64
 
75
- # assume we have an transaction already running
76
- andreas = Person.new (:name => 'andreas')
77
- andreas.friends << Person.new (:name => 'peter')
78
- andreas.friends.each {|person| puts "name #{person.name}" }
79
- Person.find("name: andreas").first.name # => 'andreas'
80
65
 
81
- ==== Neo4j::Rails::Model
66
+ ==== Example
82
67
 
83
68
  Example of using Neo4j with Rails 3 (ActiveModel)
84
69
 
85
- class User < Neo4j::Model
86
- attr_accessor :password
87
- attr_accessible :email, :password, :password_confirmation, :pending_account
70
+ class User < Neo4j::Rails::Model
71
+ attr_accessor :password
72
+ attr_accessible :email, :password, :password_confirmation, :pending_account
73
+
74
+ after_save :encrypt_password
88
75
 
89
- after_save :encrypt_password
76
+ email_regex = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
90
77
 
91
- email_regex = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
78
+ # add an exact lucene index on the email property
79
+ property :email, :index => :exact
92
80
 
93
- property :email
94
- index :email
81
+ has_one(:avatar).to(Avator)
95
82
 
96
- has_one(:avatar).to(Avator)
83
+ validates :email, :presence => true,:format => { :with => email_regex }
84
+ validates :email, :uniqueness => true, :unless => :pending_account?
85
+ accepts_nested_attributes_for :avatar, :allow_destroy => true
97
86
 
98
- validates :email, :presence => true,:format => { :with => email_regex }
99
- validates :email, :uniqueness => true, :unless => :pending_account?
100
- accepts_nested_attributes_for :avatar, :allow_destroy => true
87
+ end
101
88
 
102
- ...
103
- end
89
+ u = User.new(:name => 'kalle', :age => 42, :email => "bla@foo.com")
90
+ u.save
91
+
92
+ Make sure you are using JRuby !
104
93
 
105
94
  ==== Generate a Rails Application
106
95
 
@@ -116,33 +105,85 @@ Example of creating an Neo4j Application from scratch:
116
105
  open a webbrowser: http://localhost:3000/users
117
106
 
118
107
  To run it with Tomcat instead of WEBrick
119
-
108
+
120
109
  gem install trinidad
121
110
  trinidad
122
111
 
123
- === Architecture
112
+
113
+ === {neo4j-wrapper}[http://github.com/andreasronge/neo4j-wrapper]
114
+
115
+ {Neo4j::NodeMixin}[http://rdoc.info/github/andreasronge/neo4j-wrapper/Neo4j/NodeMixin]
116
+
117
+ {Neo4j::RelationshipMixin}[http://rdoc.info/github/andreasronge/neo4j-wrapper/Neo4j/RelationshipMixin]
118
+
119
+ ==== Example
120
+
121
+ Example of mapping a ruby class to a node and delaring properties and relationships and lucene index.
122
+
123
+ class Person
124
+ include Neo4j::NodeMixin
125
+ property :name
126
+ property :city
127
+
128
+ has_n :friends
129
+ has_one :address
130
+ index :name
131
+ end
132
+
133
+ # assume we have an transaction already running !
134
+ andreas = Person.new (:name => 'andreas')
135
+ andreas.friends << Person.new (:name => 'peter')
136
+ andreas.friends.each {|person| puts "name #{person.name}" }
137
+ Person.find("name: andreas").first.name # => 'andreas'
138
+
139
+ The Neo4j::NodeMixin and Neo4j::RelationshipMixin is implemented in the {neo4j-wrapper}[http://github.com/andreasronge/neo4j-wrapper] gem
140
+
141
+
142
+ === neo4j-core gem
143
+
144
+ {Neo4j::Node}[http://rdoc.info/github/andreasronge/neo4j-core/Neo4j/Node] The Java Neo4j Node
145
+
146
+ {Neo4j::Relationship}[http://rdoc.info/github/andreasronge/neo4j-core/Neo4j/Relationship] The Java Relationship
147
+
148
+ {Neo4j}[http://rdoc.info/github/andreasronge/neo4j-core/Neo4j] The Database
149
+
150
+ {Neo4j::Cypher}[http://rdoc.info/github/andreasronge/neo4j-core/Neo4j/Cypher] Cypher DSL, see RSpec spec/neo4j/cypher_spec
151
+
152
+ {Neo4j::Algo}[http://rdoc.info/github/andreasronge/neo4j-core/Neo4j/Algo] Included algorithms, like shortest path
153
+
154
+ ==== Example
155
+
156
+ Example of creating a Neo4j::Node
157
+
158
+ require "rubygems"
159
+ require 'neo4j'
160
+
161
+ Neo4j::Transaction.run do
162
+ node = Neo4j::Node.new(:name => 'andreas')
163
+ node.outgoing(:friends) << Neo4j::Node.new(:name => 'peter')
164
+ node.outgoing(:friends).each {|node| puts "name #{node[:name]}"}
165
+ end
166
+
167
+ The Neo4j::Node and Neo4j::Relationship is implemented in the {neo4j-core}[http://github.com/andreasronge/neo4j-core] gem.
168
+
169
+ == Architecture
124
170
 
125
171
  As you seen above, neo4j.rb consists of a three layers API:
126
172
 
127
- * Layer 1. For interacting with the basic building blocks of the graph database (node, properties and relationship), see Neo4j::Node and Neo4j::Relationship classes.
128
- * Layer 2. A binding API to Ruby objects, see Neo4j::NodeMixin and Neo4j::RelationshipMixin modules.
129
- * Layer 3. An implementation of the Rails Active Model and a subset of the Active Record API, see Neo4j::Rails::Model class.
173
+ * Layer 1, neo4j-core. For interacting with the basic building blocks of the graph database (node, properties and relationship), see Neo4j::Node and Neo4j::Relationship classes.
174
+ * Layer 2, neo4j-wrapper. A binding API to Ruby objects, see Neo4j::NodeMixin and Neo4j::RelationshipMixin modules.
175
+ * Layer 3, neo4j. An implementation of the Rails Active Model and a subset of the Active Record API, see Neo4j::RailsNode and Neo4j::RailsRelationship class.
130
176
 
131
177
  Notice that you can always access the lower layers if you want to do some more advanced. You can even access the Java API directly.
132
178
 
133
- === Presentation Materials and other URLs
134
- * {Presentation: RailsConf 2011}[http://andreasronge.github.com/neo4j-railsconf.pdf]
135
- * {Nordic Ruby 2010 May 21-23}[http://nordicruby.org/speakers#user_29]
136
- * {Neo4j wiki, check the guidelines and domain modeling gallery pages}[http://wiki.neo4j.org/content/Main_Page]
137
-
138
- === Project information
179
+ == Project information
139
180
  * {GitHub}[http://github.com/andreasronge/neo4j/tree/master]
140
181
  * {Issue Tracking}[https://github.com/andreasronge/neo4j/issues]
141
182
  * {Twitter}[http://twitter.com/ronge]
142
183
  * {Mailing list, neo4jrb@googlegroups.com}[http://groups.google.com/group/neo4jrb]
143
184
  * {Read only, old lighthouse issues}[http://neo4j.lighthouseapp.com]
144
185
 
145
- === Configuration
186
+ == Configuration
146
187
 
147
188
  {Development configuration}[http://neo4j.rubyforge.org/guides/index.html#development-and-testing-configuration] - You can configure Neo4j through the {Neo4j::Config}[http://neo4j.rubyforge.org/Neo4j/Config.html] object.
148
189
 
@@ -163,3 +204,6 @@ Do you need help - send me an email (andreas.ronge at gmail dot com).
163
204
  * Neo4j.rb - MIT, see the LICENSE file http://github.com/andreasronge/neo4j/tree/master/LICENSE.
164
205
  * Lucene - Apache, see http://lucene.apache.org/java/docs/features.html
165
206
  * \Neo4j - Dual free software/commercial license, see http://neo4j.org/
207
+
208
+ Notice there are different license for the neo4j-community, neo4j-advanced and neo4j-enterprise jar gems.
209
+ Only the neo4j-community gem is by default required.
data/lib/neo4j.rb CHANGED
@@ -1,4 +1,3 @@
1
- require 'enumerator'
2
1
  require 'forwardable'
3
2
  require 'time'
4
3
  require 'date'
@@ -6,43 +5,18 @@ require 'tmpdir'
6
5
 
7
6
  # Rails
8
7
  require 'rails/railtie'
8
+ require 'active_support/concern'
9
9
  require 'active_support/core_ext/hash/indifferent_access'
10
- require 'active_model'
11
-
12
- # core extensions
13
- require 'neo4j/core_ext/class/inheritable_attributes'
14
-
10
+ require 'active_support/core_ext/class/attribute_accessors'
11
+ require 'active_support/core_ext/class/attribute'
15
12
 
16
- module Neo4j
17
- include Java
13
+ require 'active_model'
18
14
 
19
- # Enumerator has been moved to top level in Ruby 1.9.2, make it compatible with Ruby 1.8.7
20
- Enumerator = Enumerable::Enumerator unless defined? Enumerator
21
- end
15
+ require 'neo4j-core'
16
+ require 'neo4j-wrapper'
22
17
 
23
- require 'neo4j-community'
24
- require 'neo4j/version'
25
- require 'neo4j/neo4j'
26
- require 'neo4j/paginated'
27
- require 'neo4j/node'
28
- require 'neo4j/relationship'
29
- require 'neo4j/relationship_set'
30
- require 'neo4j/type_converters/type_converters'
31
- require 'neo4j/index/index'
32
- require 'neo4j/traversal/traversal'
33
- require 'neo4j/property/property'
34
- require 'neo4j/has_n/has_n'
35
- require 'neo4j/node_mixin/node_mixin'
36
- require 'neo4j/relationship_mixin/relationship_mixin'
37
- require 'neo4j/rule/rule'
38
- require 'neo4j/rels/rels'
39
18
  require 'neo4j/rails/rails'
40
- require 'neo4j/model'
41
- require 'neo4j/migrations/migrations'
42
- require 'neo4j/algo/algo'
43
- require 'neo4j/batch/batch'
44
- require 'orm_adapter/adapters/neo4j'
45
- require 'neo4j/identity_map'
46
19
 
47
20
 
21
+ require 'orm_adapter/adapters/neo4j'
48
22
  Dir["#{File.dirname(__FILE__)}/tasks/**/*.rake"].each { |ext| load ext } if defined?(Rake) && respond_to?(:namespace)
@@ -0,0 +1,43 @@
1
+ require 'rubygems'
2
+ require 'neo4j'
3
+
4
+ class MyIndex
5
+ include Neo4j::NodeMixin
6
+ index(:name) # default :exact
7
+ index(:things)
8
+ index(:age, :field_type => Fixnum) # default :exact
9
+ index(:wheels, :field_type => Fixnum)
10
+ index(:description, :type => :fulltext)
11
+ end
12
+
13
+ def rm_db_storage
14
+ FileUtils.rm_rf Neo4j::Config[:storage_path]
15
+ raise "Can't delete db" if File.exist?(Neo4j::Config[:storage_path])
16
+ end
17
+
18
+ def finish_tx
19
+ return unless @tx
20
+ @tx.success
21
+ @tx.finish
22
+ @tx = nil
23
+ end
24
+
25
+ def new_tx
26
+ finish_tx if @tx
27
+ @tx = Neo4j::Transaction.new
28
+ end
29
+
30
+ rm_db_storage
31
+
32
+ 10.times do
33
+ t = Time.now
34
+ new_tx
35
+ (0..1000).each do
36
+ MyIndex.new :things => 'bla', :name => 'foo', :age => 42, :wheels => 53, :description => "Bla bla"
37
+ end
38
+ d1 = Time.now - t
39
+ t = Time.now
40
+ finish_tx
41
+ d2 = Time.now - t
42
+ puts "Index #{d2}, create #{d1} tot #{d1 + d2} - #{d2/(d1 + d2).round(2)}"
43
+ end
@@ -1,15 +1,16 @@
1
1
  module Neo4j::Rails
2
- # Allows accepting id for association objects. For example
3
- # class Book < Neo4j::Model
4
- # has_one(:author).to(Author)
5
- # accepts_id_for :author
6
- # end
2
+ # Allows accepting id for association objects.
3
+ # @example
4
+ # class Book < Neo4j::Rails::Model
5
+ # has_one(:author).to(Author)
6
+ # accepts_id_for :author
7
+ # end
7
8
  #
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
9
+ # # This would add a author_id getter and setter on Book. You could use
10
+ # book = Book.new(:name => 'Graph DBs', :author_id => 11)
11
+ # book.author_id # 11
12
+ # book.author_id = 13
13
+ # @note TODO: Support for has_n associations
13
14
  module AcceptId
14
15
  extend ActiveSupport::Concern
15
16
 
@@ -17,11 +18,11 @@ module Neo4j::Rails
17
18
  # Adds association_id getter and setter for one or more has_one associations
18
19
  #
19
20
  # @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
21
+ # class Book < Neo4j::Rails::Model
22
+ # has_one(:author).to(Author)
23
+ # has_one(:publisher).to(Publisher)
24
+ # accepts_id_for :author, :publisher
25
+ # end
25
26
  def accepts_id_for(*association_names)
26
27
  association_names.each do |association_name|
27
28
  define_association_id_getter(association_name)
@@ -32,8 +33,8 @@ module Neo4j::Rails
32
33
 
33
34
  # Check if model accepsts id for its association
34
35
  # @example
35
- # Book.accepts_id_for?(:author) => true
36
- # Book.accepts_id_for?(:genre) => false
36
+ # Book.accepts_id_for?(:author) => true
37
+ # Book.accepts_id_for?(:genre) => false
37
38
  def accepts_id_for?(association_name)
38
39
  accepts_id_associations.include?(association_name)
39
40
  end
@@ -56,7 +57,7 @@ module Neo4j::Rails
56
57
  class_eval %Q{
57
58
  def #{association_name}_id=(id)
58
59
  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
+ association_class = relation_target_class <= self.class ? Neo4j::Rails::Model : relation_target_class
60
61
  self.#{association_name} = id.present? ? association_class.find(id) : nil
61
62
  end
62
63
  }, __FILE__, __LINE__
@@ -10,12 +10,16 @@ module Neo4j
10
10
  # about attributes, we mean all the properties apart from those hidden ones.
11
11
  module Attributes
12
12
  extend ActiveSupport::Concern
13
+ extend TxMethods
13
14
 
14
15
  included do
15
16
  include ActiveModel::Dirty # track changes to attributes
16
17
  include ActiveModel::MassAssignmentSecurity # handle attribute hash assignment
17
18
 
18
- class_inheritable_accessor :attribute_defaults
19
+ class << self
20
+ attr_accessor :attribute_defaults
21
+ end
22
+
19
23
  self.attribute_defaults ||= {}
20
24
 
21
25
  # save the original [] and []= to use as read/write to Neo4j
@@ -29,16 +33,184 @@ module Neo4j
29
33
  # whenever we refer to [] or []=. use our local properties store
30
34
  alias_method :[], :read_local_property
31
35
  alias_method :[]=, :write_local_property
36
+
37
+ def self.inherited(sub_klass)
38
+ super
39
+ return if sub_klass.to_s[0..0] == '#' # this is really for anonymous test classes
40
+ setup_neo4j_subclass(sub_klass)
41
+ sub_klass.send(:define_method, :attribute_defaults) do
42
+ self.class.attribute_defaults
43
+ end
44
+ sub_klass.attribute_defaults = self.attribute_defaults.clone
45
+ # Hmm, could not do this from the Finders Mixin Module - should be moved
46
+ sub_klass.rule(:_all, :functions => Neo4j::Wrapper::Rule::Functions::Size.new) if sub_klass.respond_to?(:rule)
47
+ end
48
+ end
49
+
50
+ def init_on_create(*)
51
+ self._classname = self.class.to_s
52
+ write_default_attributes
53
+ write_changed_attributes
54
+ clear_changes
55
+ end
56
+
57
+ def initialize_attributes(attributes)
58
+ @_properties = {}
59
+ @_properties_before_type_cast={}
60
+ self.attributes = attributes if attributes
61
+ end
62
+
63
+ # Mass-assign attributes. Stops any protected attributes from being assigned.
64
+ def attributes=(attributes, guard_protected_attributes = true)
65
+ attributes = sanitize_for_mass_assignment(attributes) if guard_protected_attributes
66
+
67
+ multi_parameter_attributes = []
68
+ attributes.each do |k, v|
69
+ if k.to_s.include?("(")
70
+ multi_parameter_attributes << [k, v]
71
+ else
72
+ respond_to?("#{k}=") ? send("#{k}=", v) : self[k] = v
73
+ end
74
+ end
75
+
76
+ assign_multiparameter_attributes(multi_parameter_attributes)
77
+ end
78
+
79
+ def attribute_defaults
80
+ self.class.attribute_defaults
81
+ end
82
+
83
+ # Updates this resource with all the attributes from the passed-in Hash and requests that the record be saved.
84
+ # If saving fails because the resource is invalid then false will be returned.
85
+ def update_attributes(attributes)
86
+ self.attributes = attributes
87
+ save
88
+ end
89
+ tx_methods :update_attributes
90
+
91
+ # Same as #update_attributes, but raises an exception if saving fails.
92
+ def update_attributes!(attributes)
93
+ self.attributes = attributes
94
+ save!
95
+ end
96
+ tx_methods :update_attributes!
97
+
98
+ def reset_attributes
99
+ @_properties = {}
100
+ end
101
+
102
+
103
+
104
+ # Updates a single attribute and saves the record.
105
+ # This is especially useful for boolean flags on existing records. Also note that
106
+ #
107
+ # * Validation is skipped.
108
+ # * Callbacks are invoked.
109
+ # * Updates all the attributes that are dirty in this object.
110
+ #
111
+ def update_attribute(name, value)
112
+ respond_to?("#{name}=") ? send("#{name}=", value) : self[name] = value
113
+ save(:validate => false)
114
+ end
115
+
116
+ def hash
117
+ persisted? ? _java_entity.neo_id.hash : super
118
+ end
119
+
120
+ def to_param
121
+ persisted? ? neo_id.to_s : nil
122
+ end
123
+
124
+ def to_model
125
+ self
126
+ end
127
+
128
+ # Returns an Enumerable of all (primary) key attributes
129
+ # or nil if model.persisted? is false
130
+ def to_key
131
+ persisted? ? [id] : nil
132
+ end
133
+
134
+ # Return the properties from the Neo4j Node, merged with those that haven't
135
+ # yet been saved
136
+ def props
137
+ ret = {}
138
+ property_names.each do |property_name|
139
+ ret[property_name] = respond_to?(property_name) ? send(property_name) : send(:[], property_name)
140
+ end
141
+ ret
142
+ end
143
+
144
+ # Return all the attributes for this model as a hash attr => value. Doesn't
145
+ # include properties that start with <tt>_</tt>.
146
+ def attributes
147
+ ret = {}
148
+ attribute_names.each do |attribute_name|
149
+ ret[attribute_name] = self.class._decl_props[attribute_name.to_sym] ? send(attribute_name) : send(:[], attribute_name)
150
+ end
151
+ ret
152
+ end
153
+
154
+ # Known properties are either in the @_properties, the declared
155
+ # attributes or the property keys for the persisted node.
156
+ def property_names
157
+ # initialize @_properties if needed since
158
+ # we can ask property names before the object is initialized (active_support initialize callbacks, respond_to?)
159
+ @_properties ||= {}
160
+ keys = @_properties.keys + self.class._decl_props.keys.map(&:to_s)
161
+ keys += _java_entity.property_keys.to_a if persisted?
162
+ keys.flatten.uniq
163
+ end
164
+
165
+ # Known attributes are either in the @_properties, the declared
166
+ # attributes or the property keys for the persisted node. Any attributes
167
+ # that start with <tt>_</tt> are rejected
168
+ def attribute_names
169
+ property_names.reject { |property_name| _invalid_attribute_name?(property_name) }
170
+ end
171
+
172
+ # Known properties are either in the @_properties, the declared
173
+ # properties or the property keys for the persisted node
174
+ def property?(name)
175
+ return false unless @_properties
176
+ @_properties.has_key?(name) ||
177
+ self.class._decl_props.has_key?(name) ||
178
+ persisted? && super
179
+ end
180
+
181
+ def property_changed?
182
+ return !@_properties.empty? unless persisted?
183
+ !!@_properties.keys.find { |k| self._java_node[k] != @_properties[k] }
184
+ end
185
+
186
+ # Return true if method_name is the name of an appropriate attribute
187
+ # method
188
+ def attribute?(name)
189
+ name[0] != ?_ && property?(name)
32
190
  end
33
191
 
192
+
193
+ # Wrap the getter in a conversion from Java to Ruby
194
+ def read_local_property_with_type_conversion(property)
195
+ self.class._converter(property).to_ruby(read_local_property_without_type_conversion(property))
196
+ end
197
+
198
+ # Wrap the setter in a conversion from Ruby to Java
199
+ def write_local_property_with_type_conversion(property, value)
200
+ @_properties_before_type_cast[property.to_sym]=value if self.class._decl_props.has_key? property.to_sym
201
+ conv_value = self.class._converter(property.to_sym).to_java(value)
202
+ write_local_property_without_type_conversion(property, conv_value)
203
+ end
204
+
205
+
34
206
  # The behaviour of []= changes with a Rails Model, where nothing gets written
35
207
  # to Neo4j until the object is saved, during which time all the validations
36
208
  # and callbacks are run to ensure correctness
37
209
  def write_local_property(key, value)
38
210
  key_s = key.to_s
39
- if !@properties.has_key?(key_s) || @properties[key_s] != value
211
+ if !@_properties.has_key?(key_s) || @_properties[key_s] != value
40
212
  attribute_will_change!(key_s)
41
- @properties[key_s] = value.nil? ? attribute_defaults[key_s] : value
213
+ @_properties[key_s] = value.nil? ? attribute_defaults[key_s] : value
42
214
  end
43
215
  value
44
216
  end
@@ -47,29 +219,186 @@ module Neo4j
47
219
  # the DB if we don't have one
48
220
  def read_local_property(key)
49
221
  key = key.to_s
50
- if @properties.has_key?(key)
51
- @properties[key]
222
+ if @_properties.has_key?(key)
223
+ @_properties[key]
52
224
  else
53
- @properties[key] = (persisted? && _java_entity.has_property?(key)) ? read_attribute(key) : attribute_defaults[key]
225
+ @_properties[key] = (persisted? && _java_entity.has_property?(key)) ? read_attribute(key) : attribute_defaults[key]
54
226
  end
55
227
  end
56
228
 
57
- # Mass-assign attributes. Stops any protected attributes from being assigned.
58
- def attributes=(attributes, guard_protected_attributes = true)
59
- attributes = sanitize_for_mass_assignment(attributes) if guard_protected_attributes
60
229
 
61
- multi_parameter_attributes = []
62
- attributes.each do |k, v|
63
- if k.to_s.include?("(")
64
- multi_parameter_attributes << [ k, v ]
65
- else
66
- respond_to?("#{k}=") ? send("#{k}=", v) : self[k] = v
230
+ module ClassMethods
231
+ # Returns all defined properties
232
+ def columns
233
+ self._decl_props.keys
234
+ end
235
+
236
+
237
+ # Declares a property.
238
+ # It support the following hash options:
239
+ # <tt>:default</tt>,<tt>:null</tt>,<tt>:limit</tt>,<tt>:type</tt>,<tt>:index</tt>,<tt>:converter</tt>
240
+ #
241
+ # @example Set the property type,
242
+ # class Person < Neo4j::RailsModel
243
+ # property :age, :type => Time
244
+ # end
245
+ #
246
+ # @example Set the property type,
247
+ # class Person < Neo4j::RailsModel
248
+ # property :age, :default => 0
249
+ # end
250
+ # @example
251
+ # class Person < Neo4j::RailsModel
252
+ # property :age, :null => false
253
+ # end
254
+ # Property must be there
255
+ #
256
+ # @example Property has a length limit
257
+ # class Person < Neo4j::RailsModel
258
+ # property :name, :limit => 128
259
+ # end
260
+ #
261
+ # @example Index with lucene.
262
+ # class Person < Neo4j::RailsModel
263
+ # property :name, :index => :exact
264
+ # property :year, :index => :exact, :type => Fixnum # index as fixnum too
265
+ # property :description, :index => :fulltext
266
+ # end
267
+ #
268
+ # @example Using a custom converter
269
+ # module MyConverter
270
+ # def to_java(v)
271
+ # "Java:#{v}"
272
+ # end
273
+ #
274
+ # def to_ruby(v)
275
+ # "Ruby:#{v}"
276
+ # end
277
+ #
278
+ # def index_as
279
+ # String
280
+ # end
281
+ #
282
+ # extend self
283
+ # end
284
+ #
285
+ # class Person < Neo4j::RailsModel
286
+ # property :name, :converter => MyConverter
287
+ # end
288
+ #
289
+ def property(*args)
290
+ options = args.extract_options!
291
+ args.each do |property_sym|
292
+ property_setup(property_sym, options)
67
293
  end
68
294
  end
69
295
 
70
- assign_multiparameter_attributes(multi_parameter_attributes)
296
+
297
+ protected
298
+ def property_setup(property, options)
299
+ _decl_props[property] = options
300
+ handle_property_options_for(property, options)
301
+ define_property_methods_for(property, options)
302
+ define_property_before_type_cast_methods_for(property, options)
303
+ end
304
+
305
+ def handle_property_options_for(property, options)
306
+ attribute_defaults[property.to_s] = options[:default] if options.has_key?(:default)
307
+
308
+ converter = options[:converter] || Neo4j::TypeConverters.converter(_decl_props[property][:type])
309
+ _decl_props[property][:converter] = converter
310
+
311
+ if options.include?(:index)
312
+ index(property, :type => options[:index], :field_type => converter.index_as)
313
+ end
314
+
315
+ if options.has_key?(:null) && options[:null] === false
316
+ validates(property, :non_nil => true, :on => :create)
317
+ validates(property, :non_nil => true, :on => :update)
318
+ end
319
+ validates(property, :length => {:maximum => options[:limit]}) if options[:limit]
320
+ end
321
+
322
+ def define_property_methods_for(property, options)
323
+ unless method_defined?(property)
324
+ class_eval <<-RUBY, __FILE__, __LINE__
325
+ def #{property}
326
+ send(:[], "#{property}")
327
+ end
328
+ RUBY
329
+ end
330
+
331
+ unless method_defined?("#{property}=".to_sym)
332
+ class_eval <<-RUBY, __FILE__, __LINE__
333
+ def #{property}=(value)
334
+ send(:[]=, "#{property}", value)
335
+ end
336
+ RUBY
337
+ end
338
+ end
339
+
340
+ def define_property_before_type_cast_methods_for(property, options)
341
+ property_before_type_cast = "#{property}_before_type_cast"
342
+ class_eval <<-RUBY, __FILE__, __LINE__
343
+ def #{property_before_type_cast}=(value)
344
+ @_properties_before_type_cast[:#{property}]=value
345
+ end
346
+
347
+ def #{property_before_type_cast}
348
+ @_properties_before_type_cast.has_key?(:#{property}) ? @_properties_before_type_cast[:#{property}] : self.#{property}
349
+ end
350
+ RUBY
351
+ end
352
+ end
353
+
354
+
355
+ protected
356
+
357
+
358
+ # Ensure any defaults are stored in the DB
359
+ def write_default_attributes
360
+ self.class.attribute_defaults.each do |attribute, value|
361
+ write_attribute(attribute, Neo4j::TypeConverters.convert(value, attribute, self.class, false)) unless changed_attributes.has_key?(attribute) || _java_node.has_property?(attribute)
362
+ end
363
+ end
364
+
365
+ # Write attributes to the Neo4j DB only if they're altered
366
+ def write_changed_attributes
367
+ @_properties.each do |attribute, value|
368
+ write_attribute(attribute, value) if changed_attributes.has_key?(attribute)
369
+ end
370
+ end
371
+
372
+
373
+
374
+ def attribute_missing(method_id, *args, &block)
375
+ method_name = method_id.method_name
376
+ if property?(method_name)
377
+ self[method_name]
378
+ else
379
+ super
380
+ end
71
381
  end
72
382
 
383
+ # TODO THIS IS ONLY NEEDED IN ACTIVEMODEL < 3.2, ?
384
+ # To get ActiveModel::Dirty to work, we need to be able to call undeclared
385
+ # properties as though they have get methods
386
+ def method_missing(method_id, *args, &block)
387
+ method_name = method_id.to_s
388
+ if property?(method_name)
389
+ self[method_name]
390
+ else
391
+ super
392
+ end
393
+ end
394
+
395
+ def _invalid_attribute_name?(attr_name)
396
+ attr_name.to_s[0] == ?_ && !self.class._decl_props.include?(attr_name.to_sym)
397
+ end
398
+
399
+
400
+
401
+
73
402
  # Instantiates objects for all attribute classes that needs more than one constructor parameter. This is done
74
403
  # by calling new on the column type or aggregation type (through composed_of) object with these parameters.
75
404
  # So having the pairs written_on(1) = "2004", written_on(2) = "6", written_on(3) = "24", will instantiate
@@ -79,7 +408,7 @@ module Neo4j
79
408
  # attribute will be set to nil.
80
409
  def assign_multiparameter_attributes(pairs)
81
410
  execute_callstack_for_multiparameter_attributes(
82
- extract_callstack_for_multiparameter_attributes(pairs)
411
+ extract_callstack_for_multiparameter_attributes(pairs)
83
412
  )
84
413
  end
85
414
 
@@ -100,19 +429,21 @@ module Neo4j
100
429
 
101
430
  #TODO: Consider extracting hardcoded assignments into "Binders"
102
431
  value = if Neo4j::TypeConverters::TimeConverter.convert?(decl_type)
103
- instantiate_time_object(name, values)
104
- elsif Neo4j::TypeConverters::DateConverter.convert?(decl_type)
105
- begin
106
- values = values_with_empty_parameters.collect do |v| v.nil? ? 1 : v end
107
- Date.new(*values)
108
- rescue ArgumentError => ex # if Date.new raises an exception on an invalid date
109
- instantiate_time_object(name, values).to_date # we instantiate Time object and convert it back to a date thus using Time's logic in handling invalid dates
110
- end
111
- elsif Neo4j::TypeConverters::DateTimeConverter.convert?(decl_type)
112
- DateTime.new(*values)
113
- else
114
- raise "Unknown type #{decl_type}"
115
- end
432
+ instantiate_time_object(name, values)
433
+ elsif Neo4j::TypeConverters::DateConverter.convert?(decl_type)
434
+ begin
435
+ values = values_with_empty_parameters.collect do |v|
436
+ v.nil? ? 1 : v
437
+ end
438
+ Date.new(*values)
439
+ rescue ArgumentError => ex # if Date.new raises an exception on an invalid date
440
+ instantiate_time_object(name, values).to_date # we instantiate Time object and convert it back to a date thus using Time's logic in handling invalid dates
441
+ end
442
+ elsif Neo4j::TypeConverters::DateTimeConverter.convert?(decl_type)
443
+ DateTime.new(*values)
444
+ else
445
+ raise "Unknown type #{decl_type}"
446
+ end
116
447
 
117
448
  send(name + "=", value)
118
449
  end
@@ -129,12 +460,12 @@ module Neo4j
129
460
  # if self.class.send(:create_time_zone_conversion_attribute?, name, column_for_attribute(name))
130
461
  # Time.zone.local(*values)
131
462
  # else
132
- Time.time_with_datetime_fallback(self.class.default_timezone, *values)
463
+ Time.time_with_datetime_fallback(self.class.default_timezone, *values)
133
464
  # end
134
465
  end
135
466
 
136
467
  def extract_callstack_for_multiparameter_attributes(pairs)
137
- attributes = { }
468
+ attributes = {}
138
469
 
139
470
  for pair in pairs
140
471
  multiparameter_name, value = pair
@@ -142,10 +473,10 @@ module Neo4j
142
473
  attributes[attribute_name] = [] unless attributes.include?(attribute_name)
143
474
 
144
475
  parameter_value = value.empty? ? nil : type_cast_attribute_value(multiparameter_name, value)
145
- attributes[attribute_name] << [ find_parameter_position(multiparameter_name), parameter_value ]
476
+ attributes[attribute_name] << [find_parameter_position(multiparameter_name), parameter_value]
146
477
  end
147
478
 
148
- attributes.each { |name, values| attributes[name] = values.sort_by{ |v| v.first }.collect { |v| v.last } }
479
+ attributes.each { |name, values| attributes[name] = values.sort_by { |v| v.first }.collect { |v| v.last } }
149
480
  end
150
481
 
151
482
 
@@ -164,99 +495,14 @@ module Neo4j
164
495
  @changed_attributes.clear
165
496
  end
166
497
 
167
- # Return the properties from the Neo4j Node, merged with those that haven't
168
- # yet been saved
169
- def props
170
- ret = {}
171
- property_names.each do |property_name|
172
- ret[property_name] = respond_to?(property_name) ? send(property_name) : send(:[], property_name)
173
- end
174
- ret
175
- end
176
-
177
- # Return all the attributes for this model as a hash attr => value. Doesn't
178
- # include properties that start with <tt>_</tt>.
179
- def attributes
180
- ret = {}
181
- attribute_names.each do |attribute_name|
182
- ret[attribute_name] = self._decl_props[attribute_name.to_sym] ? send(attribute_name) : send(:[], attribute_name)
183
- end
184
- ret
185
- end
186
-
187
- # Known properties are either in the @properties, the declared
188
- # attributes or the property keys for the persisted node.
189
- def property_names
190
- # initialize @properties if needed since
191
- # we can ask property names before the object is initialized (active_support initialize callbacks, respond_to?)
192
- @properties ||= {}
193
- keys = @properties.keys + self.class._decl_props.keys.map { |k| k.to_s }
194
- keys += _java_entity.property_keys.to_a if persisted?
195
- keys.flatten.uniq
196
- end
197
-
198
- # Known attributes are either in the @properties, the declared
199
- # attributes or the property keys for the persisted node. Any attributes
200
- # that start with <tt>_</tt> are rejected
201
- def attribute_names
202
- property_names.reject { |property_name| _invalid_attribute_name?(property_name) }
203
- end
204
-
205
- def _invalid_attribute_name?(attr_name)
206
- attr_name.to_s[0] == ?_ && !self.class._decl_props.include?(attr_name.to_sym)
207
- end
208
-
209
- # Known properties are either in the @properties, the declared
210
- # properties or the property keys for the persisted node
211
- def property?(name)
212
- return false unless @properties
213
- @properties.has_key?(name) ||
214
- self.class._decl_props.has_key?(name) ||
215
- persisted? && super
216
- end
217
-
218
- def property_changed?
219
- return !@properties.empty? unless persisted?
220
- !!@properties.keys.find{|k| self._java_node.getProperty(k.to_s) != @properties[k] }
221
- end
222
-
223
- # Return true if method_name is the name of an appropriate attribute
224
- # method
225
- def attribute?(name)
226
- name[0] != ?_ && property?(name)
227
- end
228
-
229
498
  def _classname
230
499
  self.class.to_s
231
500
  end
232
501
 
233
502
  def _classname=(value)
234
- write_local_property_without_type_conversion("_classname",value)
235
- end
236
-
237
-
238
- # TODO THIS IS ONLY NEEDED IN ACTIVEMODEL < 3.2, ?
239
- # To get ActiveModel::Dirty to work, we need to be able to call undeclared
240
- # properties as though they have get methods
241
- def method_missing(method_id, *args, &block)
242
- method_name = method_id.to_s
243
- if property?(method_name)
244
- self[method_name]
245
- else
246
- super
247
- end
503
+ write_local_property_without_type_conversion("_classname", value)
248
504
  end
249
505
 
250
- # Wrap the getter in a conversion from Java to Ruby
251
- def read_local_property_with_type_conversion(property)
252
- Neo4j::TypeConverters.to_ruby(self.class, property, read_local_property_without_type_conversion(property))
253
- end
254
-
255
- # Wrap the setter in a conversion from Ruby to Java
256
- def write_local_property_with_type_conversion(property, value)
257
- @properties_before_type_cast[property.to_sym]=value if self.class._decl_props.has_key? property.to_sym
258
- write_local_property_without_type_conversion(property, Neo4j::TypeConverters.to_java(self.class, property, value))
259
- end
260
506
  end
261
507
  end
262
508
  end