neo4j 7.2.3 → 8.0.0.alpha.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +30 -46
  3. data/Gemfile +15 -14
  4. data/README.md +21 -14
  5. data/bin/neo4j-jars +1 -1
  6. data/lib/neo4j.rb +12 -1
  7. data/lib/neo4j/active_base.rb +68 -0
  8. data/lib/neo4j/active_base/session_registry.rb +12 -0
  9. data/lib/neo4j/active_node.rb +13 -21
  10. data/lib/neo4j/active_node/dependent/query_proxy_methods.rb +6 -6
  11. data/lib/neo4j/active_node/enum.rb +3 -6
  12. data/lib/neo4j/active_node/has_n.rb +24 -19
  13. data/lib/neo4j/active_node/has_n/association.rb +6 -2
  14. data/lib/neo4j/active_node/has_n/association/rel_factory.rb +1 -1
  15. data/lib/neo4j/active_node/has_n/association/rel_wrapper.rb +1 -1
  16. data/lib/neo4j/active_node/has_n/association_cypher_methods.rb +1 -1
  17. data/lib/neo4j/active_node/id_property.rb +52 -15
  18. data/lib/neo4j/active_node/labels.rb +32 -10
  19. data/lib/neo4j/active_node/labels/index.rb +5 -55
  20. data/lib/neo4j/active_node/node_list_formatter.rb +13 -0
  21. data/lib/neo4j/active_node/node_wrapper.rb +39 -37
  22. data/lib/neo4j/active_node/persistence.rb +27 -13
  23. data/lib/neo4j/active_node/query/query_proxy.rb +11 -9
  24. data/lib/neo4j/active_node/query/query_proxy_eager_loading.rb +4 -4
  25. data/lib/neo4j/active_node/query/query_proxy_enumerable.rb +1 -0
  26. data/lib/neo4j/active_node/query/query_proxy_link.rb +13 -9
  27. data/lib/neo4j/active_node/query/query_proxy_methods.rb +76 -8
  28. data/lib/neo4j/active_node/query/query_proxy_methods_of_mass_updating.rb +1 -1
  29. data/lib/neo4j/active_node/query_methods.rb +3 -3
  30. data/lib/neo4j/active_node/scope.rb +24 -7
  31. data/lib/neo4j/active_rel.rb +21 -3
  32. data/lib/neo4j/active_rel/initialize.rb +2 -2
  33. data/lib/neo4j/active_rel/persistence.rb +32 -6
  34. data/lib/neo4j/active_rel/persistence/query_factory.rb +3 -3
  35. data/lib/neo4j/active_rel/property.rb +9 -9
  36. data/lib/neo4j/active_rel/query.rb +6 -4
  37. data/lib/neo4j/active_rel/rel_wrapper.rb +24 -16
  38. data/lib/neo4j/active_rel/related_node.rb +5 -1
  39. data/lib/neo4j/active_rel/types.rb +2 -2
  40. data/lib/neo4j/config.rb +0 -1
  41. data/lib/neo4j/errors.rb +3 -0
  42. data/lib/neo4j/migration.rb +90 -71
  43. data/lib/neo4j/migrations.rb +10 -0
  44. data/lib/neo4j/migrations/base.rb +44 -0
  45. data/lib/neo4j/migrations/helpers.rb +101 -0
  46. data/lib/neo4j/migrations/helpers/id_property.rb +75 -0
  47. data/lib/neo4j/migrations/helpers/relationships.rb +66 -0
  48. data/lib/neo4j/migrations/helpers/schema.rb +53 -0
  49. data/lib/neo4j/migrations/migration_file.rb +24 -0
  50. data/lib/neo4j/migrations/runner.rb +110 -0
  51. data/lib/neo4j/migrations/schema_migration.rb +9 -0
  52. data/lib/neo4j/model_schema.rb +100 -0
  53. data/lib/neo4j/railtie.rb +29 -110
  54. data/lib/neo4j/schema/operation.rb +24 -13
  55. data/lib/neo4j/session_manager.rb +137 -0
  56. data/lib/neo4j/shared.rb +20 -11
  57. data/lib/neo4j/shared/attributes.rb +10 -16
  58. data/lib/neo4j/shared/callbacks.rb +3 -3
  59. data/lib/neo4j/shared/cypher.rb +1 -1
  60. data/lib/neo4j/shared/declared_properties.rb +1 -1
  61. data/lib/neo4j/shared/declared_property.rb +1 -1
  62. data/lib/neo4j/shared/enum.rb +6 -18
  63. data/lib/neo4j/shared/identity.rb +27 -21
  64. data/lib/neo4j/shared/persistence.rb +26 -17
  65. data/lib/neo4j/shared/property.rb +5 -2
  66. data/lib/neo4j/shared/query_factory.rb +4 -5
  67. data/lib/neo4j/shared/type_converters.rb +8 -9
  68. data/lib/neo4j/shared/validations.rb +1 -5
  69. data/lib/neo4j/tasks/migration.rake +83 -2
  70. data/lib/neo4j/version.rb +1 -1
  71. data/lib/rails/generators/neo4j/migration/migration_generator.rb +14 -0
  72. data/lib/rails/generators/neo4j/migration/templates/migration.erb +9 -0
  73. data/lib/rails/generators/neo4j/model/model_generator.rb +1 -3
  74. data/lib/rails/generators/neo4j_generator.rb +1 -0
  75. data/neo4j.gemspec +3 -3
  76. metadata +58 -65
  77. data/bin/rake +0 -17
  78. data/lib/neo4j/shared/permitted_attributes.rb +0 -28
@@ -10,21 +10,26 @@ module Neo4j
10
10
  include ActiveModel::Serializers::JSON
11
11
 
12
12
  module ClassMethods
13
- attr_writer :neo4j_session_name
13
+ # TODO: Deprecate neo4j_session_name(name)
14
14
 
15
- def neo4j_session_name(name)
16
- ActiveSupport::Deprecation.warn 'neo4j_session_name is deprecated and may be removed from future releases, use neo4j_session_name= instead.', caller
15
+ # remove?
16
+ def neo4j_session
17
+ Neo4j::ActiveBase.current_session
18
+ end
17
19
 
18
- @neo4j_session_name = name
20
+ # remove?
21
+ def current_transaction
22
+ Neo4j::ActiveBase.current_transaction
19
23
  end
20
24
 
21
- def neo4j_session
22
- if @neo4j_session_name
23
- Neo4j::Session.named(@neo4j_session_name) ||
24
- fail("#{self.name} is configured to use a neo4j session named #{@neo4j_session_name}, but no such session is registered with Neo4j::Session")
25
- else
26
- Neo4j::Session.current!
27
- end
25
+ # This should be used everywhere. Should make it easy
26
+ # to support a session-per-model system
27
+ def neo4j_query(*args)
28
+ Neo4j::ActiveBase.query(*args)
29
+ end
30
+
31
+ def new_query
32
+ Neo4j::ActiveBase.new_query
28
33
  end
29
34
  end
30
35
 
@@ -47,5 +52,9 @@ module Neo4j
47
52
  def declared_properties
48
53
  self.class.declared_properties
49
54
  end
55
+
56
+ def neo4j_query(*args)
57
+ self.class.neo4j_query(*args)
58
+ end
50
59
  end
51
60
  end
@@ -61,20 +61,16 @@ module Neo4j::Shared
61
61
  #
62
62
  # @raise [UnknownAttributeError] if the attribute is unknown
63
63
  def write_attribute(name, value)
64
- if respond_to? "#{name}="
65
- send "#{name}=", value
66
- else
67
- fail Neo4j::UnknownAttributeError, "unknown attribute: #{name}"
68
- end
64
+ fail Neo4j::UnknownAttributeError, "unknown attribute: #{name}" if !respond_to? "#{name}="
65
+
66
+ send "#{name}=", value
69
67
  end
70
- alias_method :[]=, :write_attribute
68
+ alias []= write_attribute
71
69
 
72
70
  def query_attribute(name)
73
- if respond_to? "#{name}?"
74
- send "#{name}?"
75
- else
76
- fail Neo4j::UnknownAttributeError, "unknown attribute: #{name}"
77
- end
71
+ fail Neo4j::UnknownAttributeError, "unknown attribute: #{name}" if !respond_to? "#{name}?"
72
+
73
+ send "#{name}?"
78
74
  end
79
75
 
80
76
  private
@@ -126,11 +122,9 @@ module Neo4j::Shared
126
122
  #
127
123
  # @return [AttributeDefinition] Attribute's definition
128
124
  def attribute(name)
129
- if dangerous_attribute?(name)
130
- fail Neo4j::DangerousAttributeError, %(an attribute method named "#{name}" would conflict with an existing method)
131
- else
132
- attribute!(name)
133
- end
125
+ fail Neo4j::DangerousAttributeError, %(an attribute method named "#{name}" would conflict with an existing method) if dangerous_attribute?(name)
126
+
127
+ attribute!(name)
134
128
  end
135
129
 
136
130
  # Returns an Array of attribute names as Strings
@@ -19,7 +19,7 @@ module Neo4j
19
19
  end
20
20
 
21
21
  def destroy #:nodoc:
22
- tx = Neo4j::Transaction.new
22
+ tx = Neo4j::ActiveBase.new_transaction
23
23
  run_callbacks(:destroy) { super }
24
24
  rescue
25
25
  @_deleted = false
@@ -49,13 +49,13 @@ module Neo4j
49
49
  end
50
50
 
51
51
  def create_model #:nodoc:
52
- Neo4j::Transaction.run do
52
+ self.class.run_transaction do
53
53
  run_callbacks(:create) { super }
54
54
  end
55
55
  end
56
56
 
57
57
  def update_model(*) #:nodoc:
58
- Neo4j::Transaction.run do
58
+ self.class.run_transaction do
59
59
  run_callbacks(:update) { super }
60
60
  end
61
61
  end
@@ -17,7 +17,7 @@ module Neo4j::Shared
17
17
  def creates_unique?
18
18
  !!@creates_unique
19
19
  end
20
- alias_method :unique?, :creates_unique?
20
+ alias unique? creates_unique?
21
21
  end
22
22
 
23
23
  module RelIdentifiers
@@ -156,7 +156,7 @@ module Neo4j::Shared
156
156
 
157
157
  def inject_defaults!(object, props)
158
158
  declared_property_defaults.each_pair do |k, v|
159
- props[k.to_sym] = v if object.send(k).nil? && props[k.to_sym].nil?
159
+ props[k.to_sym] = v.respond_to?(:call) ? v.call : v if object.send(k).nil? && props[k.to_sym].nil?
160
160
  end
161
161
  props
162
162
  end
@@ -66,7 +66,7 @@ module Neo4j::Shared
66
66
  def default_value
67
67
  options[:default]
68
68
  end
69
- alias_method :default, :default_value
69
+ alias default default_value
70
70
 
71
71
  def fail_invalid_options!
72
72
  case
@@ -36,9 +36,6 @@ module Neo4j::Shared
36
36
  # media.video_type!
37
37
  # media.video_type? # => true
38
38
  #
39
- # @example Disable index: :exact for enum elements
40
- # Media.enum type: [:image, :video, :unknown], _index: false
41
- #
42
39
  # @example Define a custom mapping for keys-numbers
43
40
  # Media.enum type: { image: 1, video: 2, unknown: 3 }
44
41
  #
@@ -67,13 +64,11 @@ module Neo4j::Shared
67
64
  end
68
65
  end
69
66
 
70
- VALID_OPTIONS_FOR_ENUMS = [:_index, :_prefix, :_suffix, :_default]
71
- DEFAULT_OPTIONS_FOR_ENUMS = {
72
- _index: true
73
- }
67
+ VALID_OPTIONS_FOR_ENUMS = [:_prefix, :_suffix]
68
+ DEFAULT_OPTIONS_FOR_ENUMS = {}
74
69
 
75
70
  def split_options_and_parameters(parameters)
76
- options = DEFAULT_OPTIONS_FOR_ENUMS.clone
71
+ options = {}
77
72
  new_parameters = {}
78
73
  parameters.each do |k, v|
79
74
  if VALID_OPTIONS_FOR_ENUMS.include? k
@@ -85,16 +80,9 @@ module Neo4j::Shared
85
80
  [options, new_parameters]
86
81
  end
87
82
 
88
- def define_property(property_name, enum_keys, options)
89
- property_options = build_property_options(enum_keys, options)
90
- property property_name, property_options
91
- serialize property_name, Neo4j::Shared::TypeConverters::EnumConverter.new(enum_keys, property_options)
92
- end
93
-
94
- def build_property_options(_enum_keys, options = {})
95
- {
96
- default: options[:_default]
97
- }
83
+ def define_property(property_name, enum_keys, _options)
84
+ property property_name, default: enum_keys.keys.first # .merge(options)
85
+ serialize property_name, Neo4j::Shared::TypeConverters::EnumConverter.new(enum_keys)
98
86
  end
99
87
 
100
88
  def define_enum_methods(property_name, enum_keys, options)
@@ -1,28 +1,34 @@
1
- module Neo4j::Shared
2
- module Identity
3
- def ==(other)
4
- other.class == self.class && other.id == id
5
- end
6
- alias_method :eql?, :==
1
+ module Neo4j
2
+ module Shared
3
+ module Identity
4
+ def ==(other)
5
+ other.class == self.class && other.id == id
6
+ end
7
+ alias eql? ==
7
8
 
8
- # Returns an Enumerable of all (primary) key attributes
9
- # or nil if model.persisted? is false
10
- def to_key
11
- _persisted_obj ? [id] : nil
12
- end
9
+ # Returns an Enumerable of all (primary) key attributes
10
+ # or nil if model.persisted? is false
11
+ def to_key
12
+ _persisted_obj ? [id] : nil
13
+ end
13
14
 
14
- # @return [Integer, nil] the neo4j id of the node if persisted or nil
15
- def neo_id
16
- _persisted_obj ? _persisted_obj.neo_id : nil
17
- end
15
+ # @return [Integer, nil] the neo4j id of the node if persisted or nil
16
+ def neo_id
17
+ _persisted_obj ? _persisted_obj.neo_id : nil
18
+ end
18
19
 
19
- def id
20
- id = neo_id
21
- id.is_a?(Integer) ? id : nil
22
- end
20
+ def id
21
+ if self.class.id_property_name
22
+ send(self.class.id_property_name)
23
+ else
24
+ # ActiveRel
25
+ neo_id
26
+ end
27
+ end
23
28
 
24
- def hash
25
- id.hash
29
+ def hash
30
+ id.hash
31
+ end
26
32
  end
27
33
  end
28
34
  end
@@ -9,7 +9,7 @@ module Neo4j::Shared
9
9
 
10
10
  def update_model
11
11
  return if !changed_attributes || changed_attributes.empty?
12
- _persisted_obj.update_props(props_for_update)
12
+ neo4j_query(query_as(:n).set(n: props_for_update))
13
13
  changed_attributes.clear
14
14
  end
15
15
 
@@ -81,14 +81,13 @@ module Neo4j::Shared
81
81
  @_create_or_updating = true
82
82
  apply_default_values
83
83
  result = _persisted_obj ? update_model : create_model
84
- if result == false
85
- Neo4j::Transaction.current.failure if Neo4j::Transaction.current
86
- false
87
- else
88
- true
89
- end
84
+ current_transaction = Neo4j::ActiveBase.current_transaction
85
+
86
+ current_transaction.mark_failed if result == false && current_transaction
87
+
88
+ result != false
90
89
  rescue => e
91
- Neo4j::Transaction.current.failure if Neo4j::Transaction.current
90
+ current_transaction.mark_failed if current_transaction
92
91
  raise e
93
92
  ensure
94
93
  @_create_or_updating = nil
@@ -97,7 +96,7 @@ module Neo4j::Shared
97
96
  def apply_default_values
98
97
  return if self.class.declared_property_defaults.empty?
99
98
  self.class.declared_property_defaults.each_pair do |key, value|
100
- self.send("#{key}=", value) if self.send(key).nil?
99
+ self.send("#{key}=", value.respond_to?(:call) ? value.call : value) if self.send(key).nil?
101
100
  end
102
101
  end
103
102
 
@@ -116,16 +115,20 @@ module Neo4j::Shared
116
115
  !_persisted_obj
117
116
  end
118
117
 
119
- alias_method :new?, :new_record?
118
+ alias new? new_record?
120
119
 
121
120
  def destroy
122
121
  freeze
123
- _persisted_obj && _persisted_obj.del
122
+
123
+ destroy_query.exec if _persisted_obj
124
+
124
125
  @_deleted = true
125
126
  end
126
127
 
127
128
  def exist?
128
- _persisted_obj && _persisted_obj.exist?
129
+ return if !_persisted_obj
130
+
131
+ neo4j_query(query_as(:n).return('ID(n)')).any?
129
132
  end
130
133
 
131
134
  # Returns +true+ if the object was destroyed.
@@ -170,14 +173,14 @@ module Neo4j::Shared
170
173
  self.attributes = process_attributes(attributes)
171
174
  save
172
175
  end
173
- alias_method :update_attributes, :update
176
+ alias update_attributes update
174
177
 
175
178
  # Same as {#update_attributes}, but raises an exception if saving fails.
176
179
  def update!(attributes)
177
180
  self.attributes = process_attributes(attributes)
178
181
  save!
179
182
  end
180
- alias_method :update_attributes!, :update!
183
+ alias update_attributes! update!
181
184
 
182
185
  def cache_key
183
186
  if self.new_record?
@@ -189,13 +192,19 @@ module Neo4j::Shared
189
192
  end
190
193
  end
191
194
 
195
+ module ClassMethods
196
+ def run_transaction(run_in_tx = true)
197
+ Neo4j::ActiveBase.run_transaction(run_in_tx) { |tx| yield tx }
198
+ end
199
+ end
200
+
192
201
  protected
193
202
 
194
203
  def increment_by_query!(match_query, attribute, by, element_name = :n)
195
204
  new_attribute = match_query.with(element_name)
196
- .set("#{element_name}.`#{attribute}` = COALESCE(#{element_name}.`#{attribute}`, 0) + {by}")
197
- .params(by: by).limit(1)
198
- .pluck("#{element_name}.`#{attribute}`").first
205
+ .set("#{element_name}.`#{attribute}` = COALESCE(#{element_name}.`#{attribute}`, 0) + {by}")
206
+ .params(by: by).limit(1)
207
+ .pluck("#{element_name}.`#{attribute}`").first
199
208
  return false unless new_attribute
200
209
  self[attribute] = new_attribute
201
210
  changed_attributes.delete(attribute)
@@ -37,7 +37,7 @@ module Neo4j::Shared
37
37
  def read_attribute(name)
38
38
  respond_to?(name) ? send(name) : nil
39
39
  end
40
- alias_method :[], :read_attribute
40
+ alias [] read_attribute
41
41
 
42
42
  def send_props(hash)
43
43
  return hash if hash.blank?
@@ -58,7 +58,7 @@ module Neo4j::Shared
58
58
  return attributes if attributes.blank?
59
59
  invalid_properties = attributes.keys.map(&:to_s) - self.attributes.keys
60
60
  invalid_properties.reject! { |name| self.respond_to?("#{name}=") }
61
- fail UndefinedPropertyError, "Undefined properties: #{invalid_properties.join(',')}" if invalid_properties.size > 0
61
+ fail UndefinedPropertyError, "Undefined properties: #{invalid_properties.join(',')}" if !invalid_properties.empty?
62
62
  end
63
63
 
64
64
  def extract_writer_methods!(attributes)
@@ -113,6 +113,7 @@ module Neo4j::Shared
113
113
 
114
114
  def_delegators :declared_properties, :serialized_properties, :serialized_properties=, :serialize, :declared_property_defaults
115
115
 
116
+ VALID_PROPERTY_OPTIONS = %w(type default index constraint serializer typecaster null).map(&:to_sym)
116
117
  # Defines a property on the class
117
118
  #
118
119
  # See active_attr gem for allowed options, e.g which type
@@ -142,6 +143,8 @@ module Neo4j::Shared
142
143
  # property :name, constraint: :unique
143
144
  # end
144
145
  def property(name, options = {})
146
+ invalid_option_keys = options.keys.map(&:to_sym) - VALID_PROPERTY_OPTIONS
147
+ fail ArgumentError, "Invalid options for property `#{name}` on `#{self.name}`: #{invalid_option_keys.join(', ')}" if invalid_option_keys.any?
145
148
  build_property(name, options) do |prop|
146
149
  attribute(prop)
147
150
  end
@@ -36,7 +36,7 @@ module Neo4j::Shared
36
36
  end
37
37
 
38
38
  def base_query
39
- @base_query || Neo4j::Session.current.query
39
+ @base_query || Neo4j::ActiveBase.new_query
40
40
  end
41
41
 
42
42
  protected
@@ -69,8 +69,7 @@ module Neo4j::Shared
69
69
 
70
70
  def create_query
71
71
  return match_query if graph_object.persisted?
72
- labels = graph_object.labels_for_create.map { |l| ":`#{l}`" }.join
73
- base_query.create("(#{identifier}#{labels} {#{identifier}_params})").params(identifier_params => graph_object.props_for_create)
72
+ base_query.create(identifier => {graph_object.labels_for_create => graph_object.props_for_create})
74
73
  end
75
74
  end
76
75
 
@@ -85,8 +84,8 @@ module Neo4j::Shared
85
84
  return match_query if graph_object.persisted?
86
85
  create_props, set_props = filtered_props
87
86
  base_query.send(graph_object.create_method, query_string).break
88
- .set(identifier => set_props)
89
- .params(:"#{identifier}_create_props" => create_props)
87
+ .set(identifier => set_props)
88
+ .params(:"#{identifier}_create_props" => create_props)
90
89
  end
91
90
 
92
91
  private
@@ -38,7 +38,7 @@ module Neo4j::Shared
38
38
  value.to_i
39
39
  end
40
40
 
41
- alias_method :to_ruby, :to_db
41
+ alias to_ruby to_db
42
42
  end
43
43
  end
44
44
 
@@ -55,7 +55,7 @@ module Neo4j::Shared
55
55
  def to_db(value)
56
56
  value.to_f
57
57
  end
58
- alias_method :to_ruby, :to_db
58
+ alias to_ruby to_db
59
59
  end
60
60
  end
61
61
 
@@ -79,7 +79,7 @@ module Neo4j::Shared
79
79
  BigDecimal.new(value.to_s)
80
80
  end
81
81
  end
82
- alias_method :to_ruby, :to_db
82
+ alias to_ruby to_db
83
83
  end
84
84
  end
85
85
 
@@ -96,7 +96,7 @@ module Neo4j::Shared
96
96
  def to_db(value)
97
97
  value.to_s
98
98
  end
99
- alias_method :to_ruby, :to_db
99
+ alias to_ruby to_db
100
100
  end
101
101
  end
102
102
 
@@ -116,7 +116,7 @@ module Neo4j::Shared
116
116
  Neo4j::Shared::Boolean
117
117
  end
118
118
 
119
- alias_method :convert_type, :db_type
119
+ alias convert_type db_type
120
120
 
121
121
  def to_db(value)
122
122
  return false if FALSE_VALUES.include?(value)
@@ -130,7 +130,7 @@ module Neo4j::Shared
130
130
  end
131
131
  end
132
132
 
133
- alias_method :to_ruby, :to_db
133
+ alias to_ruby to_db
134
134
  end
135
135
  end
136
136
 
@@ -264,9 +264,8 @@ module Neo4j::Shared
264
264
  end
265
265
 
266
266
  class EnumConverter
267
- def initialize(enum_keys, options)
267
+ def initialize(enum_keys)
268
268
  @enum_keys = enum_keys
269
- @options = options
270
269
  end
271
270
 
272
271
  def converted?(value)
@@ -289,7 +288,7 @@ module Neo4j::Shared
289
288
  @enum_keys.key(value) unless value.nil?
290
289
  end
291
290
 
292
- alias_method :call, :to_ruby
291
+ alias call to_ruby
293
292
 
294
293
  def to_db(value)
295
294
  if value.is_a?(Array)