neo4j 1.2.6-java → 2.0.0.alpha.3-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. data/CHANGELOG +30 -0
  2. data/CONTRIBUTORS +1 -0
  3. data/Gemfile +16 -4
  4. data/README.rdoc +25 -3
  5. data/bin/neo4j-jars +15 -8
  6. data/bin/neo4j-shell +0 -1
  7. data/bin/neo4j-upgrade +72 -0
  8. data/config/neo4j/config.yml +5 -4
  9. data/lib/neo4j/algo/algo.rb +0 -1
  10. data/lib/neo4j/batch/inserter.rb +5 -0
  11. data/lib/neo4j/database.rb +18 -12
  12. data/lib/neo4j/event_handler.rb +76 -9
  13. data/lib/neo4j/has_list/class_methods.rb +1 -1
  14. data/lib/neo4j/has_list/mapping.rb +13 -33
  15. data/lib/neo4j/has_n/decl_relationship_dsl.rb +17 -13
  16. data/lib/neo4j/has_n/mapping.rb +6 -23
  17. data/lib/neo4j/identity_map.rb +0 -3
  18. data/lib/neo4j/index/class_methods.rb +9 -3
  19. data/lib/neo4j/index/index.rb +2 -1
  20. data/lib/neo4j/index/indexer.rb +3 -2
  21. data/lib/neo4j/index/indexer_registry.rb +1 -1
  22. data/lib/neo4j/index/lucene_query.rb +52 -33
  23. data/lib/neo4j/neo4j.rb +19 -0
  24. data/lib/neo4j/node.rb +42 -36
  25. data/lib/neo4j/node_mixin/node_mixin.rb +9 -5
  26. data/lib/neo4j/paginated.rb +23 -0
  27. data/lib/neo4j/rails/accept_id.rb +66 -0
  28. data/lib/neo4j/rails/attributes.rb +14 -9
  29. data/lib/neo4j/rails/compositions.rb +9 -1
  30. data/lib/neo4j/rails/finders.rb +5 -1
  31. data/lib/neo4j/rails/mapping/property.rb +41 -28
  32. data/lib/neo4j/rails/model.rb +2 -0
  33. data/lib/neo4j/rails/observer.rb +61 -2
  34. data/lib/neo4j/rails/persistence.rb +57 -57
  35. data/lib/neo4j/rails/rails.rb +1 -0
  36. data/lib/neo4j/rails/railtie.rb +4 -1
  37. data/lib/neo4j/rails/rel_persistence.rb +11 -12
  38. data/lib/neo4j/rails/relationship.rb +9 -4
  39. data/lib/neo4j/rails/relationships/node_dsl.rb +15 -5
  40. data/lib/neo4j/rails/relationships/relationships.rb +42 -2
  41. data/lib/neo4j/rails/relationships/rels_dsl.rb +60 -3
  42. data/lib/neo4j/rails/relationships/storage.rb +43 -5
  43. data/lib/neo4j/rails/validations/uniqueness.rb +1 -0
  44. data/lib/neo4j/rails/versioning/versioning.rb +64 -9
  45. data/lib/neo4j/relationship.rb +79 -73
  46. data/lib/neo4j/rule/event_listener.rb +7 -1
  47. data/lib/neo4j/rule/functions/count.rb +6 -0
  48. data/lib/neo4j/rule/rule.rb +20 -5
  49. data/lib/neo4j/rule/rule_node.rb +33 -20
  50. data/lib/neo4j/to_java.rb +5 -0
  51. data/lib/neo4j/traversal/traverser.rb +38 -1
  52. data/lib/neo4j/type_converters/type_converters.rb +56 -5
  53. data/lib/neo4j/version.rb +1 -1
  54. data/lib/neo4j.rb +3 -49
  55. data/neo4j.gemspec +2 -2
  56. metadata +191 -216
  57. data/bin/neo4j-shell~ +0 -108
  58. data/lib/Gemfile~ +0 -3
  59. data/lib/config2.yml~ +0 -86
  60. data/lib/neo4j/jars/core/geronimo-jta_1.1_spec-1.1.1.jar +0 -0
  61. data/lib/neo4j/jars/core/lucene-core-3.1.0.jar +0 -0
  62. data/lib/neo4j/jars/core/neo4j-backup-1.4.1.jar +0 -0
  63. data/lib/neo4j/jars/core/neo4j-graph-algo-1.4.1.jar +0 -0
  64. data/lib/neo4j/jars/core/neo4j-index-1.3-1.3.M01.jar +0 -0
  65. data/lib/neo4j/jars/core/neo4j-kernel-1.4.1.jar +0 -0
  66. data/lib/neo4j/jars/core/neo4j-lucene-index-1.4.1.jar +0 -0
  67. data/lib/neo4j/jars/ha/log4j-1.2.16.jar +0 -0
  68. data/lib/neo4j/jars/ha/neo4j-com-1.4.1.jar +0 -0
  69. data/lib/neo4j/jars/ha/neo4j-ha-1.4.1.jar +0 -0
  70. data/lib/neo4j/jars/ha/neo4j-jmx-1.4.1.jar +0 -0
  71. data/lib/neo4j/jars/ha/neo4j-management-1.4.1.jar +0 -0
  72. data/lib/neo4j/jars/ha/neo4j-shell-1.4.1.jar +0 -0
  73. data/lib/neo4j/jars/ha/netty-3.2.1.Final.jar +0 -0
  74. data/lib/neo4j/jars/ha/org.apache.servicemix.bundles.jline-0.9.94_1.jar +0 -0
  75. data/lib/neo4j/jars/ha/zookeeper-3.3.2.jar +0 -0
  76. data/lib/neo4j/paginate.rb +0 -25
  77. data/lib/perf.rb~ +0 -36
  78. data/lib/test.rb~ +0 -2
@@ -34,7 +34,7 @@ module Neo4j
34
34
  class DeclRelationshipDsl
35
35
  include Neo4j::ToJava
36
36
 
37
- attr_reader :target_class, :dir, :rel_type
37
+ attr_reader :target_class, :source_class, :dir, :rel_type
38
38
 
39
39
  def initialize(method_id, has_one, target_class)
40
40
  @dir = :outgoing
@@ -42,6 +42,7 @@ module Neo4j
42
42
  @has_one = has_one
43
43
  @rel_type = method_id
44
44
  @target_class = target_class
45
+ @source_class = target_class
45
46
  end
46
47
 
47
48
  def to_s
@@ -63,7 +64,7 @@ module Neo4j
63
64
  def java_dir
64
65
  dir_to_java(@dir)
65
66
  end
66
-
67
+
67
68
  def each_node(node, &block) #:nodoc:
68
69
  node._java_node.getRelationships(java_rel_type, java_dir).each do |rel|
69
70
  block.call(rel.getOtherNode(node).wrapper)
@@ -141,7 +142,7 @@ module Neo4j
141
142
  if (Class === target)
142
143
  # handle e.g. has_n(:friends).to(class)
143
144
  @target_class = target
144
- @rel_type = "#{@target_class}##{@method_id}"
145
+ @rel_type = "#{@source_class}##{@method_id}"
145
146
  elsif (Symbol === target)
146
147
  # handle e.g. has_n(:friends).to(:knows)
147
148
  @rel_type = target.to_s
@@ -163,7 +164,7 @@ module Neo4j
163
164
  # class FileNode
164
165
  # include Neo4j::NodeMixin
165
166
  # # will only traverse any incoming relationship of type files from node FileNode
166
- # has_one(:folder).from(FileNode, :files)
167
+ # has_one(:folder).from(FolderNode, :files)
167
168
  # end
168
169
  #
169
170
  # file = FileNode.new
@@ -183,7 +184,7 @@ module Neo4j
183
184
  # end
184
185
  #
185
186
  # file = FileNode.new
186
- # # create an outgoing relationship of type 'FileNode#files' from folder node to file
187
+ # # create an outgoing relationship of type 'files' from folder node to file
187
188
  # file.folder = FolderNode.new
188
189
  #
189
190
  #
@@ -192,14 +193,9 @@ module Neo4j
192
193
 
193
194
  if (args.size > 1)
194
195
  # handle specified (prefixed) relationship, e.g. has_n(:known_by).from(clazz, :type)
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
+ @rel_type = "#{@target_class}##{args[1]}"
198
+ @relationship_name = args[1]
203
199
  elsif (Symbol === args[0])
204
200
  # handle unspecified (unprefixed) relationship, e.g. has_n(:known_by).from(:type)
205
201
  @rel_type = args[0]
@@ -235,7 +231,15 @@ module Neo4j
235
231
  end
236
232
 
237
233
  def relationship_class # :nodoc:
238
- @relationship
234
+ if !@relationship_name.nil? && @relationship.nil?
235
+ other_class_dsl = @target_class._decl_rels[@relationship_name]
236
+ if other_class_dsl
237
+ @relationship = other_class_dsl.relationship_class
238
+ else
239
+ Neo4j.logger.warn "Unknown outgoing relationship #{@relationship_name} on #{@target_class}"
240
+ end
241
+ end
242
+ @relationship
239
243
  end
240
244
  end
241
245
  end
@@ -7,7 +7,7 @@ module Neo4j
7
7
 
8
8
  # The object created by a has_n or has_one Neo4j::NodeMixin class method which enables creating and traversal of nodes.
9
9
  #
10
- # Includes the Enumerable and WillPaginate mixins.
10
+ # Includes the Enumerable mixin.
11
11
  # The Neo4j::Mapping::ClassMethods::Relationship#has_n and Neo4j::Mapping::ClassMethods::Relationship#one
12
12
  # methods returns an object of this type.
13
13
  #
@@ -16,8 +16,6 @@ module Neo4j
16
16
  #
17
17
  class Mapping
18
18
  include Enumerable
19
- include WillPaginate::Finders::Base
20
-
21
19
  include ToJava
22
20
 
23
21
  def initialize(node, dsl) # :nodoc:
@@ -30,7 +28,7 @@ module Neo4j
30
28
  end
31
29
 
32
30
  def size
33
- self.to_a.size
31
+ self.to_a.size # TODO: Optimise this
34
32
  end
35
33
 
36
34
  alias_method :length, :size
@@ -50,13 +48,13 @@ module Neo4j
50
48
  end
51
49
 
52
50
  # Required by the Enumerable mixin.
53
- def each(&block)
54
- @dsl.each_node(@node, &block)
51
+ def each
52
+ @dsl.each_node(@node) {|n| yield n} # Should use yield here as passing &block through doesn't always work (why?)
55
53
  end
56
54
 
57
55
  # returns none wrapped nodes, you may get better performance using this method
58
- def _each(&block)
59
- @dsl._each_node(@node, &block)
56
+ def _each
57
+ @dsl._each_node(@node) {|n| yield n}
60
58
  end
61
59
 
62
60
  # Returns an real ruby array.
@@ -64,21 +62,6 @@ module Neo4j
64
62
  self.to_a
65
63
  end
66
64
 
67
- def wp_query(options, pager, args, &block) #:nodoc:
68
- page = pager.current_page || 1
69
- to = pager.per_page * page
70
- from = to - pager.per_page
71
- i = 0
72
- res = []
73
- _each do |node|
74
- res << node.wrapper if i >= from
75
- i += 1
76
- break if i >= to
77
- end
78
- pager.replace res
79
- pager.total_entries ||= self.size # TODO, this could be very slow to do
80
- end
81
-
82
65
  # Returns true if there are no node in this type of relationship
83
66
  def empty?
84
67
  first == nil
@@ -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
@@ -53,13 +53,19 @@ module Neo4j
53
53
  #
54
54
  # Person.index_names[:fulltext] => 'my_location'
55
55
  # Person.index_names[:exact] => 'Foo_Person-exact' # default Location
56
- # Notice in versions <= 1.0.0.beta.29 the default location was 'Foo::Person-exact'
57
- # which does not work on Windows [lighthouse ticket #147]
56
+ #
57
+ # The index can be prefixed, see Neo4j#threadlocal_ref_node= and multi dendency.
58
58
  #
59
59
  # :singleton-method: index_names
60
60
 
61
61
 
62
- def_delegators :@_indexer, :index, :find, :index?, :index_type?, :delete_index_type, :rm_field_type, :add_index, :rm_index, :index_type_for, :index_names
62
+ ##
63
+ # Returns a hash of which indexes has been defined and the type of index (:exact or :fulltext)
64
+ #
65
+ # :singleton-method: index_types
66
+
67
+
68
+ def_delegators :@_indexer, :index, :find, :index?, :index_type?, :delete_index_type, :rm_field_type, :add_index, :rm_index, :index_type_for, :index_names, :index_types
63
69
 
64
70
  # Sets which indexer should be used for the given node class.
65
71
  # You can share an indexer between several different classes.
@@ -19,7 +19,8 @@ module Neo4j
19
19
  # Neo4j::Index::ClassMethods::index
20
20
  #
21
21
  def add_index(field, value=self[field])
22
- self.class.add_index(wrapped_entity, field.to_s, value)
22
+ converted_value = Neo4j::TypeConverters.convert(value, field, self.class)
23
+ self.class.add_index(wrapped_entity, field.to_s, converted_value)
23
24
  end
24
25
 
25
26
  # Removes an index on the given property.
@@ -2,6 +2,7 @@ module Neo4j
2
2
  module Index
3
3
  class Indexer
4
4
  attr_reader :indexer_for, :field_types, :via_relationships, :entity_type, :parent_indexers, :via_relationships
5
+ alias_method :index_types, :field_types # public method accessible from node.index_types
5
6
 
6
7
  def initialize(clazz, type) #:nodoc:
7
8
  # part of the unique name of the index
@@ -155,7 +156,7 @@ module Neo4j
155
156
  end
156
157
 
157
158
  def update_single_index_on(node, field, old_val, new_val) #:nodoc:
158
- if @field_types.include?(field)
159
+ if @field_types.has_key?(field)
159
160
  rm_index(node, field, old_val) if old_val
160
161
  add_index(node, field, new_val) if new_val
161
162
  end
@@ -322,7 +323,7 @@ module Neo4j
322
323
  def index_names
323
324
  @index_names ||= Hash.new do |hash, index_type|
324
325
  default_filename = index_prefix + @indexer_for.to_s.gsub('::', '_')
325
- hash.fetch(index_type) {"#{default_filename}-#{index_type}"}
326
+ hash.fetch(index_type) {"#{default_filename}_#{index_type}"}
326
327
  end
327
328
  end
328
329
 
@@ -10,7 +10,7 @@ module Neo4j
10
10
  def create_for(this_clazz, using_other_clazz, type)
11
11
  @@indexers ||= {}
12
12
  index = Indexer.new(this_clazz, type)
13
- index.inherit_fields_from(@@indexers[using_other_clazz.to_s])
13
+ index.inherit_fields_from(@@indexers[using_other_clazz.to_s]) if @@indexers[using_other_clazz.to_s]
14
14
  @@indexers[this_clazz.to_s] = index
15
15
  end
16
16
 
@@ -37,8 +37,7 @@ module Neo4j
37
37
  #
38
38
  class LuceneQuery
39
39
  include Enumerable
40
- include WillPaginate::Finders::Base
41
- attr_accessor :left_and_query, :left_or_query
40
+ attr_accessor :left_and_query, :left_or_query, :right_not_query
42
41
 
43
42
  def initialize(index, decl_props, query, params={})
44
43
  @index = index
@@ -52,30 +51,9 @@ module Neo4j
52
51
  end
53
52
  end
54
53
 
55
- def wp_query(options, pager, args, &block) #:nodoc:
56
- @params[:page] = pager.current_page
57
- @params[:per_page] = pager.per_page
58
- pager.replace [*self]
59
- pager.total_entries = size
60
- end
61
-
62
- # Since we include the Ruby Enumerable mixin we need this method.
54
+ # Implements the Ruby +Enumerable+ interface
63
55
  def each
64
- if @params.include?(:per_page)
65
- # paginate the result, used by the will_paginate gem
66
- page = @params[:page] || 1
67
- per_page = @params[:per_page]
68
- to = per_page * page
69
- from = to - per_page
70
- i = 0
71
- hits.each do |node|
72
- yield node.wrapper if i >= from
73
- i += 1
74
- break if i >= to
75
- end
76
- else
77
- hits.each { |n| yield n.wrapper }
78
- end
56
+ hits.each { |x| yield x.wrapper }
79
57
  end
80
58
 
81
59
  # Close hits
@@ -156,9 +134,33 @@ module Neo4j
156
134
  # Person.find(:name=>'kalle').and(:age => 3)
157
135
  #
158
136
  def and(query2)
159
- new_query = LuceneQuery.new(@index, @decl_props, query2)
160
- new_query.left_and_query = self
161
- new_query
137
+ LuceneQuery.new(@index, @decl_props, query2).tap { |new_query| new_query.left_and_query = self }
138
+ end
139
+
140
+ # Create an OR lucene query.
141
+ #
142
+ # ==== Parameters
143
+ # query2 :: the query that should be OR together
144
+ #
145
+ # ==== Example
146
+ #
147
+ # Person.find(:name=>'kalle').or(:age => 3)
148
+ #
149
+ def or(query2)
150
+ LuceneQuery.new(@index, @decl_props, query2).tap { |new_query| new_query.left_or_query = self }
151
+ end
152
+
153
+ # Create a NOT lucene query.
154
+ #
155
+ # ==== Parameters
156
+ # query2 :: the query that should exclude matching results
157
+ #
158
+ # ==== Example
159
+ #
160
+ # Person.find(:age => 3).not(:name=>'kalle')
161
+ #
162
+ def not(query2)
163
+ LuceneQuery.new(@index, @decl_props, query2).tap { |new_query| new_query.right_not_query = self }
162
164
  end
163
165
 
164
166
 
@@ -175,11 +177,26 @@ module Neo4j
175
177
  end
176
178
 
177
179
  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
180
+ build_composite_query(@left_and_query.build_query, query, org.apache.lucene.search.BooleanClause::Occur::MUST)
181
+ end
182
+
183
+ def build_or_query(query) #:nodoc:
184
+ build_composite_query(@left_or_query.build_query, query, org.apache.lucene.search.BooleanClause::Occur::SHOULD)
185
+ end
186
+
187
+ def build_not_query(query) #:nodoc:
188
+ right_query = @right_not_query.build_query
189
+ composite_query = org.apache.lucene.search.BooleanQuery.new
190
+ composite_query.add(query, org.apache.lucene.search.BooleanClause::Occur::MUST_NOT)
191
+ composite_query.add(right_query, org.apache.lucene.search.BooleanClause::Occur::MUST)
192
+ composite_query
193
+ end
194
+
195
+ def build_composite_query(left_query, right_query, opeartor) #:nodoc:
196
+ composite_query = org.apache.lucene.search.BooleanQuery.new
197
+ composite_query.add(left_query, opeartor)
198
+ composite_query.add(right_query, opeartor)
199
+ composite_query
183
200
  end
184
201
 
185
202
  def build_sort_query(query) #:nodoc:
@@ -224,6 +241,8 @@ module Neo4j
224
241
  query = @query
225
242
  query = build_hash_query(query) if Hash === query
226
243
  query = build_and_query(query) if @left_and_query
244
+ query = build_or_query(query) if @left_or_query
245
+ query = build_not_query(query) if @right_not_query
227
246
  query = build_sort_query(query) if @order
228
247
  query
229
248
  end
data/lib/neo4j/neo4j.rb CHANGED
@@ -13,6 +13,9 @@ require 'neo4j/database'
13
13
  #
14
14
  module Neo4j
15
15
 
16
+ # The version of the Neo4j jar files
17
+ NEO_VERSION = Neo4j::Community::VERSION
18
+
16
19
  class << self
17
20
  # Start Neo4j using the default database.
18
21
  # This is usally not required since the database will be started automatically when it is used.
@@ -71,6 +74,22 @@ module Neo4j
71
74
  Neo4j::Config
72
75
  end
73
76
 
77
+ # Executes a Cypher Query
78
+ # Check the neo4j http://docs.neo4j.org/chunked/milestone/cypher-query-lang.html
79
+ # Returns an enumerable of hash values.
80
+ #
81
+ # === Usage
82
+ #
83
+ # q = Neo4j.query("START n=node({node}) RETURN n", 'node' => @node.neo_id)
84
+ # q.first['n'] #=> the @node
85
+ # q.columns.first => 'n'
86
+ #
87
+ def query(query, params = {})
88
+ engine = org.neo4j.cypher.javacompat.ExecutionEngine.new(db)
89
+ engine.execute(query, params)
90
+ end
91
+
92
+
74
93
  # Returns the logger used by neo4j.
75
94
  # If not specified (with Neo4j.logger=) it will use the standard Ruby logger.
76
95
  # You can change standard logger threshold by configuration :logger_level.
data/lib/neo4j/node.rb CHANGED
@@ -7,42 +7,6 @@ require 'neo4j/equal'
7
7
  require 'neo4j/load'
8
8
 
9
9
  module Neo4j
10
-
11
- org.neo4j.kernel.impl.core.NodeProxy.class_eval do
12
- include Neo4j::Property
13
- include Neo4j::Rels
14
- include Neo4j::Traversal
15
- include Neo4j::Equal
16
- include Neo4j::Index
17
-
18
- def del #:nodoc:
19
- rels.each {|r| r.del}
20
- delete
21
- nil
22
- end
23
-
24
- def exist? #:nodoc:
25
- Neo4j::Node.exist?(self)
26
- end
27
-
28
- def wrapped_entity #:nodoc:
29
- self
30
- end
31
-
32
- def wrapper #:nodoc:
33
- self.class.wrapper(self)
34
- end
35
-
36
- def _java_node #:nodoc:
37
- self
38
- end
39
-
40
- def class #:nodoc:
41
- Neo4j::Node
42
- end
43
- end
44
-
45
-
46
10
  # A node in the graph with properties and relationships to other entities.
47
11
  # Along with relationships, nodes are the core building blocks of the Neo4j data representation model.
48
12
  # Node has three major groups of operations: operations that deal with relationships, operations that deal with properties and operations that traverse the node space.
@@ -259,6 +223,48 @@ module Neo4j
259
223
  nil
260
224
  end
261
225
 
226
+ def extend_java_class(java_clazz) #:nodoc:
227
+ java_clazz.class_eval do
228
+ include Neo4j::Property
229
+ include Neo4j::Rels
230
+ include Neo4j::Traversal
231
+ include Neo4j::Equal
232
+ include Neo4j::Index
233
+
234
+ def del #:nodoc:
235
+ rels.each { |r| r.del }
236
+ delete
237
+ nil
238
+ end
239
+
240
+ def exist? #:nodoc:
241
+ Neo4j::Node.exist?(self)
242
+ end
243
+
244
+ def wrapped_entity #:nodoc:
245
+ self
246
+ end
247
+
248
+ def wrapper #:nodoc:
249
+ self.class.wrapper(self)
250
+ end
251
+
252
+ def _java_node #:nodoc:
253
+ self
254
+ end
255
+
256
+ def class #:nodoc:
257
+ Neo4j::Node
258
+ end
259
+ end
260
+ end
262
261
  end
263
262
  end
263
+
264
+ # org.neo4j.kernel.HighlyAvailableGraphDatabase$LookupNode
265
+ #
266
+ Neo4j::Node.extend_java_class(org.neo4j.kernel.impl.core.NodeProxy)
267
+
268
+
269
+
264
270
  end
@@ -36,8 +36,6 @@ module Neo4j
36
36
  # * Neo4j::Index::ClassMethods
37
37
  # * Neo4j::HasList::ClassMethods
38
38
  #
39
- # This class also includes the class mixin WillPaginate::Finders::Base, see http://github.com/mislav/will_paginate/wiki
40
- #
41
39
  module NodeMixin
42
40
  include Neo4j::Index
43
41
 
@@ -80,7 +78,7 @@ module Neo4j
80
78
  def _java_entity
81
79
  @_java_node
82
80
  end
83
-
81
+
84
82
  # Trigger rules.
85
83
  # You don't normally need to call this method (except in Migration) since
86
84
  # it will be triggered automatically by the Neo4j::Rule::Rule
@@ -99,6 +97,13 @@ module Neo4j
99
97
  self
100
98
  end
101
99
 
100
+ def pagination_source(*a)
101
+ binding.pry
102
+ end
103
+
104
+ def self.pagination_source(*a)
105
+ binding.pry
106
+ end
102
107
 
103
108
  def self.included(c) # :nodoc:
104
109
  c.instance_eval do
@@ -119,7 +124,6 @@ module Neo4j
119
124
  c.extend Neo4j::Rule::ClassMethods
120
125
  c.extend Neo4j::HasList::ClassMethods
121
126
  c.extend Neo4j::Index::ClassMethods
122
- c.extend WillPaginate::Finders::Base
123
127
 
124
128
  def c.inherited(subclass)
125
129
  # inherit the index properties
@@ -131,7 +135,7 @@ module Neo4j
131
135
  super
132
136
  end
133
137
 
134
- c.node_indexer c
138
+ c.node_indexer c unless c == Neo4j::Rails::Model
135
139
  end
136
140
  end
137
141
  end
@@ -0,0 +1,23 @@
1
+ module Neo4j
2
+
3
+ # The class provides the pagination based on the given source.
4
+ # The source must be an Enumerable implementing methods drop, first and count (or size).
5
+ # This can be used to paginage any Enumerable collection and
6
+ # provides the integration point for other gems, like will_paginate and kaminari.
7
+ class Paginated
8
+ include Enumerable
9
+ attr_reader :items, :total, :current_page
10
+
11
+ def initialize(items, total, current_page)
12
+ @items, @total, @current_page = items, total, current_page
13
+ end
14
+
15
+ def self.create_from(source, page, per_page)
16
+ partial = source.drop((page-1) * per_page).first(per_page)
17
+ Paginated.new(partial, source.count, page)
18
+ end
19
+
20
+ delegate :each, :to => :items
21
+ delegate :size, :[], :to => :items
22
+ end
23
+ end
@@ -0,0 +1,66 @@
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
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
@@ -38,7 +38,7 @@ module Neo4j
38
38
  key_s = key.to_s
39
39
  if !@properties.has_key?(key_s) || @properties[key_s] != value
40
40
  attribute_will_change!(key_s)
41
- @properties[key_s] = value
41
+ @properties[key_s] = value.nil? ? attribute_defaults[key_s] : value
42
42
  end
43
43
  value
44
44
  end
@@ -98,16 +98,17 @@ module Neo4j
98
98
  send(name + "=", nil)
99
99
  else
100
100
 
101
- value = if :time == decl_type
101
+ #TODO: Consider extracting hardcoded assignments into "Binders"
102
+ value = if Neo4j::TypeConverters::TimeConverter.convert?(decl_type)
102
103
  instantiate_time_object(name, values)
103
- elsif :date == decl_type
104
+ elsif Neo4j::TypeConverters::DateConverter.convert?(decl_type)
104
105
  begin
105
106
  values = values_with_empty_parameters.collect do |v| v.nil? ? 1 : v end
106
107
  Date.new(*values)
107
108
  rescue ArgumentError => ex # if Date.new raises an exception on an invalid date
108
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
109
110
  end
110
- elsif :datetime == decl_type
111
+ elsif Neo4j::TypeConverters::DateTimeConverter.convert?(decl_type)
111
112
  DateTime.new(*values)
112
113
  else
113
114
  raise "Unknown type #{decl_type}"
@@ -201,8 +202,8 @@ module Neo4j
201
202
  # Known properties are either in the @properties, the declared
202
203
  # properties or the property keys for the persisted node
203
204
  def property?(name)
204
- @properties.keys.include?(name) ||
205
- self.class._decl_props.map { |k| k.to_s }.include?(name) ||
205
+ @properties.has_key?(name) ||
206
+ self.class._decl_props.has_key?(name) ||
206
207
  begin
207
208
  persisted? && super
208
209
  rescue org.neo4j.graphdb.NotFoundException
@@ -216,9 +217,13 @@ module Neo4j
216
217
  def attribute?(name)
217
218
  name[0] != ?_ && property?(name)
218
219
  end
219
-
220
+
220
221
  def _classname
221
- self[:_classname]
222
+ self.class.to_s
223
+ end
224
+
225
+ def _classname=(value)
226
+ write_local_property_without_type_conversion("_classname",value)
222
227
  end
223
228
 
224
229
  # To get ActiveModel::Dirty to work, we need to be able to call undeclared
@@ -248,7 +253,7 @@ module Neo4j
248
253
 
249
254
  # Wrap the setter in a conversion from Ruby to Java
250
255
  def write_local_property_with_type_conversion(property, value)
251
- self.send("#{property}_before_type_cast=", value) if respond_to?("#{property}_before_type_cast=")
256
+ @properties_before_type_cast[property.to_sym]=value if self.class._decl_props.has_key? property.to_sym
252
257
  write_local_property_without_type_conversion(property, Neo4j::TypeConverters.to_java(self.class, property, value))
253
258
  end
254
259
  end