neo4j 4.0.0 → 4.1.0

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 (58) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +10 -0
  3. data/Gemfile +6 -16
  4. data/README.md +5 -2
  5. data/bin/neo4j-jars +6 -6
  6. data/lib/neo4j.rb +13 -9
  7. data/lib/neo4j/active_node.rb +9 -9
  8. data/lib/neo4j/active_node/dependent.rb +11 -0
  9. data/lib/neo4j/active_node/dependent/association_methods.rb +28 -0
  10. data/lib/neo4j/active_node/dependent/query_proxy_methods.rb +48 -0
  11. data/lib/neo4j/active_node/has_n.rb +124 -112
  12. data/lib/neo4j/active_node/has_n/association.rb +45 -30
  13. data/lib/neo4j/active_node/id_property.rb +22 -19
  14. data/lib/neo4j/active_node/initialize.rb +2 -4
  15. data/lib/neo4j/active_node/labels.rb +23 -22
  16. data/lib/neo4j/active_node/node_wrapper.rb +5 -8
  17. data/lib/neo4j/active_node/orm_adapter.rb +2 -4
  18. data/lib/neo4j/active_node/persistence.rb +5 -10
  19. data/lib/neo4j/active_node/property.rb +3 -4
  20. data/lib/neo4j/active_node/query.rb +27 -6
  21. data/lib/neo4j/active_node/query/query_proxy.rb +65 -110
  22. data/lib/neo4j/active_node/query/query_proxy_enumerable.rb +67 -0
  23. data/lib/neo4j/active_node/query/query_proxy_find_in_batches.rb +0 -1
  24. data/lib/neo4j/active_node/query/query_proxy_methods.rb +29 -28
  25. data/lib/neo4j/active_node/query_methods.rb +6 -6
  26. data/lib/neo4j/active_node/reflection.rb +3 -2
  27. data/lib/neo4j/active_node/rels.rb +1 -1
  28. data/lib/neo4j/active_node/scope.rb +13 -8
  29. data/lib/neo4j/active_node/validations.rb +5 -6
  30. data/lib/neo4j/active_rel.rb +1 -2
  31. data/lib/neo4j/active_rel/callbacks.rb +3 -3
  32. data/lib/neo4j/active_rel/persistence.rb +9 -7
  33. data/lib/neo4j/active_rel/property.rb +12 -4
  34. data/lib/neo4j/active_rel/query.rb +6 -8
  35. data/lib/neo4j/active_rel/rel_wrapper.rb +0 -2
  36. data/lib/neo4j/active_rel/related_node.rb +4 -5
  37. data/lib/neo4j/active_rel/types.rb +4 -6
  38. data/lib/neo4j/active_rel/validations.rb +0 -1
  39. data/lib/neo4j/config.rb +11 -23
  40. data/lib/neo4j/core/query.rb +1 -1
  41. data/lib/neo4j/migration.rb +17 -18
  42. data/lib/neo4j/paginated.rb +4 -4
  43. data/lib/neo4j/railtie.rb +19 -19
  44. data/lib/neo4j/shared.rb +7 -3
  45. data/lib/neo4j/shared/callbacks.rb +15 -4
  46. data/lib/neo4j/shared/identity.rb +2 -2
  47. data/lib/neo4j/shared/persistence.rb +10 -21
  48. data/lib/neo4j/shared/property.rb +17 -30
  49. data/lib/neo4j/shared/rel_type_converters.rb +1 -3
  50. data/lib/neo4j/shared/type_converters.rb +13 -25
  51. data/lib/neo4j/shared/validations.rb +3 -3
  52. data/lib/neo4j/tasks/migration.rake +7 -7
  53. data/lib/neo4j/type_converters.rb +1 -1
  54. data/lib/neo4j/version.rb +1 -1
  55. data/lib/rails/generators/neo4j/model/model_generator.rb +16 -12
  56. data/lib/rails/generators/neo4j_generator.rb +18 -18
  57. data/neo4j.gemspec +22 -18
  58. metadata +103 -1
@@ -8,13 +8,17 @@ module Neo4j
8
8
  include ActiveModel::Serializers::JSON
9
9
 
10
10
  module ClassMethods
11
- def neo4j_session_name (name)
11
+ attr_writer :neo4j_session_name
12
+
13
+ def neo4j_session_name(name)
14
+ ActiveSupport::Deprecation.warn 'neo4j_session_name is deprecated and may be removed from future releases, use neo4j_session_name= instead.', caller
15
+
12
16
  @neo4j_session_name = name
13
17
  end
14
18
 
15
19
  def neo4j_session
16
20
  if @neo4j_session_name
17
- Neo4j::Session.named(@neo4j_session_name) || raise("#{self.name} is configured to use a neo4j session named #{@neo4j_session_name}, but no such session is registered with Neo4j::Session")
21
+ Neo4j::Session.named(@neo4j_session_name) || fail("#{self.name} is configured to use a neo4j session named #{@neo4j_session_name}, but no such session is registered with Neo4j::Session")
18
22
  else
19
23
  Neo4j::Session.current!
20
24
  end
@@ -29,4 +33,4 @@ module Neo4j
29
33
  end
30
34
  end
31
35
  end
32
- end
36
+ end
@@ -9,12 +9,20 @@ module Neo4j
9
9
 
10
10
  included do
11
11
  include ActiveModel::Validations::Callbacks
12
- define_model_callbacks :initialize, :find, :only => :after
12
+ define_model_callbacks :initialize, :find, only: :after
13
13
  define_model_callbacks :save, :create, :update, :destroy
14
14
  end
15
15
 
16
16
  def destroy #:nodoc:
17
+ tx = Neo4j::Transaction.new
17
18
  run_callbacks(:destroy) { super }
19
+ rescue
20
+ @_deleted = false
21
+ @attributes = @attributes.dup
22
+ tx.mark_failed
23
+ raise
24
+ ensure
25
+ tx.close if tx
18
26
  end
19
27
 
20
28
  def touch(*) #:nodoc:
@@ -28,13 +36,16 @@ module Neo4j
28
36
  end
29
37
 
30
38
  def create_model #:nodoc:
31
- run_callbacks(:create) { super }
39
+ Neo4j::Transaction.run do
40
+ run_callbacks(:create) { super }
41
+ end
32
42
  end
33
43
 
34
44
  def update_model(*) #:nodoc:
35
- run_callbacks(:update) { super }
45
+ Neo4j::Transaction.run do
46
+ run_callbacks(:update) { super }
47
+ end
36
48
  end
37
49
  end
38
-
39
50
  end
40
51
  end
@@ -1,7 +1,7 @@
1
1
  module Neo4j::Shared
2
2
  module Identity
3
- def ==(o)
4
- o.class == self.class && o.id == id
3
+ def ==(other)
4
+ other.class == self.class && other.id == id
5
5
  end
6
6
  alias_method :eql?, :==
7
7
 
@@ -1,6 +1,5 @@
1
1
  module Neo4j::Shared
2
2
  module Persistence
3
-
4
3
  extend ActiveSupport::Concern
5
4
  include Neo4j::Shared::TypeConverters
6
5
 
@@ -8,7 +7,7 @@ module Neo4j::Shared
8
7
 
9
8
  def update_model
10
9
  if changed_attributes && !changed_attributes.empty?
11
- changed_props = attributes.select{|k,v| changed_attributes.include?(k)}
10
+ changed_props = attributes.select { |k, _| changed_attributes.include?(k) }
12
11
  changed_props = convert_properties_to :db, changed_props
13
12
  _persisted_obj.update_props(changed_props)
14
13
  changed_attributes.clear
@@ -34,21 +33,21 @@ module Neo4j::Shared
34
33
  def create_or_update
35
34
  # since the same model can be created or updated twice from a relationship we have to have this guard
36
35
  @_create_or_updating = true
37
- result = persisted? ? update_model : create_model
38
- unless result != false
39
- Neo4j::Transaction.current.fail if Neo4j::Transaction.current
36
+ result = _persisted_obj ? update_model : create_model
37
+ if result == false
38
+ Neo4j::Transaction.current.failure if Neo4j::Transaction.current
40
39
  false
41
40
  else
42
41
  true
43
42
  end
44
43
  rescue => e
45
- Neo4j::Transaction.current.fail if Neo4j::Transaction.current
44
+ Neo4j::Transaction.current.failure if Neo4j::Transaction.current
46
45
  raise e
47
46
  ensure
48
47
  @_create_or_updating = nil
49
48
  end
50
49
 
51
- # Returns +true+ if the record is persisted, i.e. its not a new record and it was not destroyed
50
+ # Returns +true+ if the record is persisted, i.e. it's not a new record and it was not destroyed
52
51
  def persisted?
53
52
  !new_record? && !destroyed?
54
53
  end
@@ -58,9 +57,10 @@ module Neo4j::Shared
58
57
  !_persisted_obj
59
58
  end
60
59
 
61
- alias :new? :new_record?
60
+ alias_method :new?, :new_record?
62
61
 
63
62
  def destroy
63
+ freeze
64
64
  _persisted_obj && _persisted_obj.del
65
65
  @_deleted = true
66
66
  end
@@ -77,12 +77,11 @@ module Neo4j::Shared
77
77
 
78
78
  # @return [Hash] all defined and none nil properties
79
79
  def props
80
- attributes.reject{|k,v| v.nil?}.symbolize_keys
80
+ attributes.reject { |_, v| v.nil? }.symbolize_keys
81
81
  end
82
82
 
83
83
  # @return true if the attributes hash has been frozen
84
84
  def frozen?
85
- freeze_if_deleted
86
85
  @attributes.frozen?
87
86
  end
88
87
 
@@ -91,16 +90,6 @@ module Neo4j::Shared
91
90
  self
92
91
  end
93
92
 
94
- def freeze_if_deleted
95
- unless new_record?
96
- # TODO - Neo4j::IdentityMap.remove_node_by_id(neo_id)
97
- unless self.class.load_entity(neo_id)
98
- @_deleted = true
99
- freeze
100
- end
101
- end
102
- end
103
-
104
93
  def reload
105
94
  return self if new_record?
106
95
  clear_association_cache
@@ -113,7 +102,7 @@ module Neo4j::Shared
113
102
  end
114
103
 
115
104
  def reload_from_database
116
- # TODO - Neo4j::IdentityMap.remove_node_by_id(neo_id)
105
+ # TODO: - Neo4j::IdentityMap.remove_node_by_id(neo_id)
117
106
  if reloaded = self.class.load_entity(neo_id)
118
107
  send(:attributes=, reloaded.attributes)
119
108
  end
@@ -13,11 +13,11 @@ module Neo4j::Shared
13
13
  class MultiparameterAssignmentError < StandardError; end
14
14
  class IllegalPropertyError < StandardError; end
15
15
 
16
- ILLEGAL_PROPS = %w[from_node to_node start_node end_node]
16
+ ILLEGAL_PROPS = %w(from_node to_node start_node end_node)
17
17
 
18
18
  attr_reader :_persisted_obj
19
19
 
20
- def initialize(attributes={}, options={})
20
+ def initialize(attributes = {}, options = {})
21
21
  attributes = process_attributes(attributes)
22
22
  @relationship_props = self.class.extract_association_attributes!(attributes)
23
23
  writer_method_props = extract_writer_methods!(attributes)
@@ -39,7 +39,7 @@ module Neo4j::Shared
39
39
 
40
40
  def default_properties=(properties)
41
41
  keys = self.class.default_properties.keys
42
- @default_properties = properties.select {|key| keys.include?(key) }
42
+ @default_properties = properties.select { |key| keys.include?(key) }
43
43
  end
44
44
 
45
45
  def default_property(key)
@@ -64,14 +64,12 @@ module Neo4j::Shared
64
64
  # Raises an error if there are any keys left which haven't been defined as properties on the model
65
65
  def validate_attributes!(attributes)
66
66
  invalid_properties = attributes.keys.map(&:to_s) - self.attributes.keys
67
- raise UndefinedPropertyError, "Undefined properties: #{invalid_properties.join(',')}" if invalid_properties.size > 0
67
+ fail UndefinedPropertyError, "Undefined properties: #{invalid_properties.join(',')}" if invalid_properties.size > 0
68
68
  end
69
69
 
70
70
  def extract_writer_methods!(attributes)
71
- attributes.keys.inject({}) do |writer_method_props, key|
71
+ attributes.keys.each_with_object({}) do |key, writer_method_props|
72
72
  writer_method_props[key] = attributes.delete(key) if self.respond_to?("#{key}=")
73
-
74
- writer_method_props
75
73
  end
76
74
  end
77
75
 
@@ -97,7 +95,7 @@ module Neo4j::Shared
97
95
  values = (values.keys.min..values.keys.max).map { |i| values[i] }
98
96
  field = self.class.attributes[key.to_sym]
99
97
  new_attributes[key] = instantiate_object(field, values)
100
- rescue => e
98
+ rescue
101
99
  raise MultiparameterAssignmentError, "error on assignment #{values.inspect} to #{key}"
102
100
  end
103
101
  end
@@ -105,14 +103,13 @@ module Neo4j::Shared
105
103
  end
106
104
 
107
105
  def instantiate_object(field, values_with_empty_parameters)
108
- return nil if values_with_empty_parameters.all? { |v| v.nil? }
106
+ return nil if values_with_empty_parameters.all?(&:nil?)
109
107
  values = values_with_empty_parameters.collect { |v| v.nil? ? 1 : v }
110
108
  klass = field[:type]
111
109
  klass ? klass.new(*values) : values
112
110
  end
113
111
 
114
112
  module ClassMethods
115
-
116
113
  # Defines a property on the class
117
114
  #
118
115
  # See active_attr gem for allowed options, e.g which type
@@ -141,7 +138,7 @@ module Neo4j::Shared
141
138
  # # declare a property which can have any value
142
139
  # property :name, constraint: :unique
143
140
  # end
144
- def property(name, options={})
141
+ def property(name, options = {})
145
142
  check_illegal_prop(name)
146
143
  magic_properties(name, options)
147
144
  attribute(name, options)
@@ -149,7 +146,7 @@ module Neo4j::Shared
149
146
  end
150
147
 
151
148
  def undef_property(name)
152
- raise ArgumentError, "Argument `#{name}` not an attribute" if not attribute_names.include?(name.to_s)
149
+ fail ArgumentError, "Argument `#{name}` not an attribute" if not attribute_names.include?(name.to_s)
153
150
 
154
151
  attribute_methods(name).each do |method|
155
152
  undef_method(method)
@@ -176,12 +173,12 @@ module Neo4j::Shared
176
173
  end
177
174
 
178
175
  def default_property_values(instance)
179
- default_properties.each_with_object({}) do |(key, block),result|
176
+ default_properties.each_with_object({}) do |(key, block), result|
180
177
  result[key] = block.call(instance)
181
178
  end
182
179
  end
183
180
 
184
- def attribute!(name, options={})
181
+ def attribute!(name, options = {})
185
182
  super(name, options)
186
183
  define_method("#{name}=") do |value|
187
184
  typecast_value = typecast_attribute(_attribute_typecaster(name), value)
@@ -195,38 +192,28 @@ module Neo4j::Shared
195
192
  def constraint_or_index(name, options)
196
193
  # either constraint or index, do not set both
197
194
  if options[:constraint]
198
- raise "unknown constraint type #{options[:constraint]}, only :unique supported" if options[:constraint] != :unique
195
+ fail "unknown constraint type #{options[:constraint]}, only :unique supported" if options[:constraint] != :unique
199
196
  constraint(name, type: :unique)
200
197
  elsif options[:index]
201
- raise "unknown index type #{options[:index]}, only :exact supported" if options[:index] != :exact
198
+ fail "unknown index type #{options[:index]}, only :exact supported" if options[:index] != :exact
202
199
  index(name, options) if options[:index] == :exact
203
200
  end
204
201
  end
205
202
 
206
203
  def check_illegal_prop(name)
207
204
  if ILLEGAL_PROPS.include?(name.to_s)
208
- raise IllegalPropertyError, "#{name} is an illegal property"
205
+ fail IllegalPropertyError, "#{name} is an illegal property"
209
206
  end
210
207
  end
211
208
 
212
209
  # Tweaks properties
213
210
  def magic_properties(name, options)
214
- set_stamp_type(name, options)
215
- set_time_as_datetime(options)
216
- end
217
-
218
- def set_stamp_type(name, options)
219
- options[:type] ||= DateTime if (name.to_sym == :created_at || name.to_sym == :updated_at)
220
- end
211
+ options[:type] ||= DateTime if name.to_sym == :created_at || name.to_sym == :updated_at
221
212
 
222
- # ActiveAttr does not handle "Time", Rails and Neo4j.rb 2.3 did
223
- # Convert it to DateTime in the interest of consistency
224
- def set_time_as_datetime(options)
213
+ # ActiveAttr does not handle "Time", Rails and Neo4j.rb 2.3 did
214
+ # Convert it to DateTime in the interest of consistency
225
215
  options[:type] = DateTime if options[:type] == Time
226
216
  end
227
-
228
217
  end
229
-
230
218
  end
231
-
232
219
  end
@@ -1,10 +1,8 @@
1
1
  module Neo4j::Shared
2
-
3
2
  # This module controls changes to relationship type based on Neo4j::Config.transform_rel_type.
4
3
  # It's used whenever a rel type is automatically determined based on ActiveRel model name or
5
4
  # association type.
6
5
  module RelTypeConverters
7
-
8
6
  def decorated_rel_type(type)
9
7
  @decorated_rel_type ||= Neo4j::Shared::RelTypeConverters.decorated_rel_type(type)
10
8
  end
@@ -41,4 +39,4 @@ module Neo4j::Shared
41
39
  end
42
40
  end
43
41
  end
44
- end
42
+ end
@@ -1,10 +1,8 @@
1
1
  module Neo4j::Shared
2
2
  module TypeConverters
3
-
4
3
  # Converts Date objects to Java long types. Must be timezone UTC.
5
4
  class DateConverter
6
5
  class << self
7
-
8
6
  def convert_type
9
7
  Date
10
8
  end
@@ -18,14 +16,12 @@ module Neo4j::Shared
18
16
  return nil if value.nil?
19
17
  Time.at(value).utc.to_date
20
18
  end
21
-
22
19
  end
23
20
  end
24
21
 
25
22
  # Converts DateTime objects to and from Java long types. Must be timezone UTC.
26
23
  class DateTimeConverter
27
24
  class << self
28
-
29
25
  def convert_type
30
26
  DateTime
31
27
  end
@@ -50,18 +46,16 @@ module Neo4j::Shared
50
46
  when String
51
47
  DateTime.strptime(value, '%Y-%m-%d %H:%M:%S %z')
52
48
  else
53
- raise ArgumentError, "Invalid value type for DateType property: #{value.inspect}"
49
+ fail ArgumentError, "Invalid value type for DateType property: #{value.inspect}"
54
50
  end
55
51
 
56
52
  DateTime.civil(t.year, t.month, t.day, t.hour, t.min, t.sec)
57
53
  end
58
-
59
54
  end
60
55
  end
61
56
 
62
57
  class TimeConverter
63
58
  class << self
64
-
65
59
  def convert_type
66
60
  Time
67
61
  end
@@ -81,14 +75,12 @@ module Neo4j::Shared
81
75
  return nil if value.nil?
82
76
  Time.at(value).utc
83
77
  end
84
-
85
78
  end
86
79
  end
87
80
 
88
81
  # Converts hash to/from YAML
89
82
  class YAMLConverter
90
83
  class << self
91
-
92
84
  def convert_type
93
85
  Hash
94
86
  end
@@ -108,7 +100,6 @@ module Neo4j::Shared
108
100
  # Converts hash to/from JSON
109
101
  class JSONConverter
110
102
  class << self
111
-
112
103
  def convert_type
113
104
  JSON
114
105
  end
@@ -130,24 +121,23 @@ module Neo4j::Shared
130
121
  def convert_properties_to(medium, properties)
131
122
  # Perform type conversion
132
123
  serialize = self.respond_to?(:serialized_properties) ? self.serialized_properties : {}
133
- properties = properties.inject({}) do |new_attributes, key_value_pair|
124
+
125
+ properties.each_with_object({}) do |key_value_pair, new_attributes|
134
126
  attr, value = key_value_pair
135
127
 
136
128
  # skip "secret" undeclared attributes such as uuid
137
129
  next new_attributes unless self.class.attributes[attr]
138
130
 
139
- type = serialize.has_key?(attr.to_sym) ? serialize[attr.to_sym] : self.class._attribute_type(attr)
131
+ type = serialize.key?(attr.to_sym) ? serialize[attr.to_sym] : self.class._attribute_type(attr)
140
132
  new_attributes[attr] = if TypeConverters.converters[type].nil?
141
- value
142
- else
143
- TypeConverters.send "to_#{medium}", value, type
144
- end
145
- new_attributes
133
+ value
134
+ else
135
+ TypeConverters.send "to_#{medium}", value, type
136
+ end
146
137
  end
147
138
  end
148
139
 
149
140
  class << self
150
-
151
141
  # Converts the value to ruby from a Neo4j database value if there is a converter for given type
152
142
  def to_ruby(value, type = nil)
153
143
  found_converter = converters[type]
@@ -162,13 +152,11 @@ module Neo4j::Shared
162
152
 
163
153
  def converters
164
154
  @converters ||= begin
165
- Neo4j::Shared::TypeConverters.constants.find_all do |c|
166
- Neo4j::Shared::TypeConverters.const_get(c).respond_to?(:convert_type)
167
- end.map do |c|
168
- Neo4j::Shared::TypeConverters.const_get(c)
169
- end.inject({}) do |ack, t|
170
- ack[t.convert_type] = t
171
- ack
155
+ Neo4j::Shared::TypeConverters.constants.each_with_object({}) do |constant_name, result|
156
+ constant = Neo4j::Shared::TypeConverters.const_get(constant_name)
157
+ if constant.respond_to?(:convert_type)
158
+ result[constant.convert_type] = constant
159
+ end
172
160
  end
173
161
  end
174
162
  end
@@ -14,7 +14,7 @@ module Neo4j
14
14
  # @param [Hash] options the options to create a message with.
15
15
  # @option options [true, false] :validate if false no validation will take place
16
16
  # @return [Boolean] true if it saved it successfully
17
- def save(options={})
17
+ def save(options = {})
18
18
  result = perform_validations(options) ? super : false
19
19
  if !result
20
20
  Neo4j::Transaction.current.failure if Neo4j::Transaction.current
@@ -31,7 +31,7 @@ module Neo4j
31
31
 
32
32
  private
33
33
 
34
- def perform_validations(options={})
34
+ def perform_validations(options = {})
35
35
  perform_validation = case options
36
36
  when Hash
37
37
  options[:validate] != false
@@ -45,4 +45,4 @@ module Neo4j
45
45
  end
46
46
  end
47
47
  end
48
- end
48
+ end