neo4j 5.0.0 → 5.0.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: df42076f21c3f31cf2cde7b6d226af5c3f27ffd4
4
- data.tar.gz: 284cff951e6666fe88f49147c05d89f59be231fd
3
+ metadata.gz: 276174c101922613a542e86d6e9cd493c1f48a24
4
+ data.tar.gz: c9a94adc2fd8d557adc44fc499b368bd95c9e489
5
5
  SHA512:
6
- metadata.gz: dd03334a23759e25ecf0aa6a3586ad8b08b8650312505254e84e06e43502fab6e1ae775f9b86218db686baefdfec11e8078dfd7de378bcffe0ac1055682bc2bc
7
- data.tar.gz: 408d0968f7796141d8f04f81fd91b08e859141001285eba1a7f4d79f30ad2be8a2f3f7ed46964b853743e497f9726c8d8b615f3ad3f3508fac132e9f0a946db5
6
+ metadata.gz: 983f69b3c76689e65b951a36db641ecc3c57001f3a6bbbace282ec4ef856509e802f798dc5d0efe1b985d27692bc64f438ed7c9c0d477f95097b162c5fa1bee5
7
+ data.tar.gz: 087725cfbc3cf345af9f0594ee7e7363fddba832182760b8ef5e2ae367d970d28a194f2f79997dd5cca9cdb313368589d469240015e21cca4ce8c788535a4279
@@ -4,7 +4,22 @@ This file should follow the standards specified on [http://keepachangelog.com/]
4
4
  This project adheres to [Semantic Versioning](http://semver.org/).
5
5
 
6
6
  ## [Unreleased][unreleased]
7
- - Nothing yet, placeholder
7
+
8
+ ## [5.0.1] - 2015-06-23
9
+
10
+ ### Fixed
11
+ - Longstanding bug that would prevent association changes (`<<` and ActiveRel.create) in Rails after `reload!` had been called, see https://github.com/neo4jrb/neo4j/pull/839
12
+ - ActiveNode#inspect wasn't displaying the id_property
13
+ - Default property values and magic typecasting not being inherited correctly
14
+
15
+ ### Changed
16
+ - In the absense of a `model_class` key, associations defined in ActiveNode models will use `from_/to_class` defined in `rel_class` to find destination. (Huge thanks to @olance, #838)
17
+ - ActiveRel's DSL was made a bit friendlier by making the `type`, `from_class` and `to_class` methods return their set values when called without arguments.
18
+ - Reworked ActiveRel's wrapper to behave more like ActiveNode's, removing some duplicate methods and moving others to Neo4j::Shared, resulting in a big performance boost when returning large numbers of rels.
19
+ - Updated gemspec to require neo4j-core 5.0.1+
20
+
21
+ ### Added
22
+ - ActiveRel was given `find_or_create_by`, usable across single associations.
8
23
 
9
24
  ## [5.0.0] - 2015-06-18
10
25
 
data/Gemfile CHANGED
@@ -17,4 +17,5 @@ group 'test' do
17
17
  gem 'its'
18
18
  gem 'test-unit'
19
19
  gem 'overcommit'
20
+ gem 'colored'
20
21
  end
@@ -35,6 +35,7 @@ require 'neo4j/shared/validations'
35
35
  require 'neo4j/shared/identity'
36
36
  require 'neo4j/shared/serialized_properties'
37
37
  require 'neo4j/shared/typecaster'
38
+ require 'neo4j/shared/initialize'
38
39
  require 'neo4j/shared'
39
40
 
40
41
  require 'neo4j/active_rel/callbacks'
@@ -17,6 +17,14 @@ module Neo4j
17
17
  apply_vars_from_options(options)
18
18
  end
19
19
 
20
+ def derive_model_class
21
+ return @model_class unless @model_class.nil?
22
+ return nil if relationship_class.nil?
23
+ dir_class = direction == :in ? :from_class : :to_class
24
+ return false if relationship_class.send(dir_class).to_s.to_sym == :any
25
+ relationship_class.send(dir_class)
26
+ end
27
+
20
28
  def target_class_option(model_class)
21
29
  case model_class
22
30
  when nil
@@ -41,10 +49,12 @@ module Neo4j
41
49
  end
42
50
 
43
51
  def target_class_names
44
- @target_class_names ||= if @target_class_option.is_a?(Array)
45
- @target_class_option.map(&:to_s)
46
- elsif @target_class_option
47
- [@target_class_option.to_s]
52
+ option = target_class_option(derive_model_class)
53
+
54
+ @target_class_names ||= if option.is_a?(Array)
55
+ option.map(&:to_s)
56
+ elsif option
57
+ [option.to_s]
48
58
  end
49
59
  end
50
60
 
@@ -77,7 +87,7 @@ module Neo4j
77
87
 
78
88
  def relationship_type(create = false)
79
89
  case
80
- when @relationship_class
90
+ when relationship_class
81
91
  relationship_class_type
82
92
  when @relationship_type
83
93
  @relationship_type
@@ -88,30 +98,19 @@ module Neo4j
88
98
  end
89
99
  end
90
100
 
91
- attr_reader :relationship_class
101
+ attr_reader :relationship_class_name
92
102
 
93
103
  def relationship_class_type
94
- @relationship_class = @relationship_class.constantize if @relationship_class.class == String || @relationship_class == Symbol
95
- @relationship_class._type.to_sym
104
+ relationship_class._type.to_sym
96
105
  end
97
106
 
98
- def relationship_class_name
99
- @relationship_class_name ||= @relationship_class.respond_to?(:constantize) ? @relationship_class : @relationship_class.name
100
- end
101
-
102
- def relationship_clazz
103
- @relationship_clazz ||= if @relationship_class.is_a?(String)
104
- @relationship_class.constantize
105
- elsif @relationship_class.is_a?(Symbol)
106
- @relationship_class.to_s.constantize
107
- else
108
- @relationship_class
109
- end
107
+ def relationship_class
108
+ @relationship_class ||= @relationship_class_name && @relationship_class_name.constantize
110
109
  end
111
110
 
112
111
  def inject_classname(properties)
113
- return properties unless @relationship_class
114
- properties[Neo4j::Config.class_name_property] = relationship_class_name if relationship_clazz.cached_class?(true)
112
+ return properties unless relationship_class
113
+ properties[Neo4j::Config.class_name_property] = relationship_class_name if relationship_class.cached_class?(true)
115
114
  properties
116
115
  end
117
116
 
@@ -179,11 +178,12 @@ module Neo4j
179
178
  private
180
179
 
181
180
  def apply_vars_from_options(options)
182
- @target_class_option = target_class_option(options[:model_class])
181
+ @relationship_class_name = options[:rel_class] && options[:rel_class].to_s
182
+ @relationship_type = options[:type] && options[:type].to_sym
183
+
184
+ @model_class = options[:model_class]
183
185
  @callbacks = {before: options[:before], after: options[:after]}
184
186
  @origin = options[:origin] && options[:origin].to_sym
185
- @relationship_class = options[:rel_class]
186
- @relationship_type = options[:type] && options[:type].to_sym
187
187
  @dependent = options[:dependent].try(:to_sym)
188
188
  @unique = options[:unique]
189
189
  end
@@ -1,5 +1,7 @@
1
1
  module Neo4j::ActiveNode::Initialize
2
2
  extend ActiveSupport::Concern
3
+ include Neo4j::Shared::Initialize
4
+
3
5
  attr_reader :called_by
4
6
 
5
7
  # called when loading the node from the database
@@ -11,27 +13,4 @@ module Neo4j::ActiveNode::Initialize
11
13
  changed_attributes && changed_attributes.clear
12
14
  @attributes = convert_and_assign_attributes(properties)
13
15
  end
14
-
15
- # Implements the Neo4j::Node#wrapper and Neo4j::Relationship#wrapper method
16
- # so that we don't have to care if the node is wrapped or not.
17
- # @return self
18
- def wrapper
19
- self
20
- end
21
-
22
- private
23
-
24
- def convert_and_assign_attributes(properties)
25
- @attributes ||= self.class.attributes_nil_hash.dup
26
- stringify_attributes!(@attributes, properties)
27
- self.default_properties = properties
28
- self.class.declared_property_manager.convert_properties_to(self, :ruby, @attributes)
29
- end
30
-
31
- def stringify_attributes!(attr, properties)
32
- properties.each_pair do |k, v|
33
- key = self.class.declared_property_manager.string_key(k)
34
- attr[key] = v
35
- end
36
- end
37
16
  end
@@ -192,7 +192,7 @@ module Neo4j
192
192
  (arg.is_a?(Integer) || arg.is_a?(String)) ? @model.find_by(@model.id_property_name => arg) : arg
193
193
  end.compact
194
194
 
195
- if @model && other_nodes.any? { |other_node| !other_node.is_a?(@model) }
195
+ if @model && other_nodes.any? { |other_node| !other_node.class.mapped_label_names.include?(@model.mapped_label_name) }
196
196
  fail ArgumentError, "Node must be of the association's class when model is specified"
197
197
  end
198
198
 
@@ -65,7 +65,7 @@ module Neo4j
65
65
  # TODO: update this with public API methods if/when they are exposed
66
66
  def limit_value
67
67
  return unless self.query.clause?(:limit)
68
- limit_clause = self.query.send(:clauses).select { |clause| clause.is_a?(Neo4j::Core::QueryClauses::LimitClause) }.first
68
+ limit_clause = self.query.send(:clauses).find { |clause| clause.is_a?(Neo4j::Core::QueryClauses::LimitClause) }
69
69
  limit_clause.instance_variable_get(:@arg)
70
70
  end
71
71
 
@@ -161,6 +161,19 @@ module Neo4j
161
161
  nodes.each { |node| self << node }
162
162
  end
163
163
 
164
+ # When called, this method returns a single node that satisfies the match specified in the params hash.
165
+ # If no existing node is found to satisfy the match, one is created or associated as expected.
166
+ def find_or_create_by(params)
167
+ fail 'Method invalid when called on Class objects' unless source_object
168
+ result = self.where(params).first
169
+ return result unless result.nil?
170
+ Neo4j::Transaction.run do
171
+ node = model.find_or_create_by(params)
172
+ self << node
173
+ return node
174
+ end
175
+ end
176
+
164
177
  # Returns all relationships between a node and its last link in the QueryProxy chain, destroys them in Ruby. Callbacks will be run.
165
178
  def destroy(node)
166
179
  self.rels_to(node).map!(&:destroy)
@@ -1,29 +1,19 @@
1
1
  module Neo4j::ActiveRel
2
2
  module Initialize
3
3
  extend ActiveSupport::Concern
4
-
5
- attr_reader :_persisted_obj
4
+ include Neo4j::Shared::Initialize
6
5
 
7
6
  # called when loading the rel from the database
8
- # @param [Hash] properties properties of this relationship
9
- # @param [Neo4j::Relationship] start_node the starting node in the relationship.
10
- # @param [Neo4j::Relationship] end_node the ending node in the relationship
7
+ # @param [Neo4j::Embedded::EmbeddedRelationship, Neo4j::Server::CypherRelationship] persisted_rel properties of this relationship
8
+ # @param [Neo4j::Relationship] from_node_id The neo_id of the starting node of this rel
9
+ # @param [Neo4j::Relationship] to_node_id The neo_id of the ending node of this rel
11
10
  # @param [String] type the relationship type
12
11
  def init_on_load(persisted_rel, from_node_id, to_node_id, type)
13
- @_persisted_obj = persisted_rel
14
12
  @rel_type = type
13
+ @_persisted_obj = persisted_rel
15
14
  changed_attributes && changed_attributes.clear
16
- @attributes = attributes.merge(persisted_rel.props.stringify_keys)
15
+ @attributes = convert_and_assign_attributes(persisted_rel.props)
17
16
  load_nodes(from_node_id, to_node_id)
18
- self.default_properties = persisted_rel.props
19
- @attributes = self.class.declared_property_manager.convert_properties_to(self, :ruby, @attributes)
20
- end
21
-
22
- # Implements the Neo4j::Node#wrapper and Neo4j::Relationship#wrapper method
23
- # so that we don't have to care if the node is wrapped or not.
24
- # @return self
25
- def wrapper
26
- self
27
17
  end
28
18
  end
29
19
  end
@@ -60,10 +60,16 @@ module Neo4j::ActiveRel
60
60
 
61
61
  next if [:any, false].include?(type_class)
62
62
 
63
- fail ModelClassInvalidError, "Node class was #{node.class}, expected #{type_class}" unless node.is_a?(type_class.to_s.constantize)
63
+ unless node.class.mapped_label_names.include?(type_class.to_s.constantize.mapped_label_name)
64
+ fail ModelClassInvalidError, type_validation_error_message(node, type_class)
65
+ end
64
66
  end
65
67
  end
66
68
 
69
+ def type_validation_error_message(node, type_class)
70
+ "Node class was #{node.class} (#{node.class.object_id}), expected #{type_class} (#{type_class.object_id})"
71
+ end
72
+
67
73
  def _create_rel(from_node, to_node, *args)
68
74
  props = self.class.default_property_values(self)
69
75
  props.merge!(args[0]) if args[0].is_a?(Hash)
@@ -75,8 +81,6 @@ module Neo4j::ActiveRel
75
81
  _rel_creation_query(from_node, to_node, props)
76
82
  end
77
83
 
78
- private
79
-
80
84
  N1_N2_STRING = 'n1, n2'
81
85
  ACTIVEREL_NODE_MATCH_STRING = 'ID(n1) = {n1_neo_id} AND ID(n2) = {n2_neo_id}'
82
86
  def _rel_creation_query(from_node, to_node, props)
@@ -21,7 +21,6 @@ module Neo4j::ActiveRel
21
21
 
22
22
  def initialize(attributes = {}, options = {})
23
23
  super(attributes, options)
24
-
25
24
  send_props(@relationship_props) unless @relationship_props.nil?
26
25
  end
27
26
 
@@ -36,8 +35,16 @@ module Neo4j::ActiveRel
36
35
  end
37
36
  end
38
37
 
38
+ def id_property_name
39
+ false
40
+ end
41
+
39
42
  %w(to_class from_class).each do |direction|
40
- define_method("#{direction}") { |argument| instance_variable_set("@#{direction}", argument) }
43
+ define_method("#{direction}") do |argument = nil|
44
+ return self.instance_variable_get("@#{direction}") if argument.nil?
45
+ instance_variable_set("@#{direction}", argument)
46
+ end
47
+
41
48
  define_method("_#{direction}") { instance_variable_get "@#{direction}" }
42
49
  end
43
50
 
@@ -2,7 +2,6 @@ class Neo4j::Relationship
2
2
  module Wrapper
3
3
  def wrapper
4
4
  props.symbolize_keys!
5
- # return self unless props.is_a?(Hash)
6
5
  begin
7
6
  most_concrete_class = sorted_wrapper_classes
8
7
  wrapped_rel = most_concrete_class.constantize.new
@@ -21,7 +20,7 @@ class Neo4j::Relationship
21
20
  end
22
21
 
23
22
  def class_from_type
24
- Neo4j::ActiveRel::Types::WRAPPED_CLASSES[rel_type] || rel_type.camelize
23
+ Neo4j::ActiveRel::Types::WRAPPED_CLASSES[rel_type] || Neo4j::ActiveRel::Types::WRAPPED_CLASSES[rel_type] = rel_type.camelize
25
24
  end
26
25
  end
27
26
  end
@@ -31,10 +31,13 @@ module Neo4j
31
31
  subclass.type subclass.namespaced_model_name, true
32
32
  end
33
33
 
34
- # @param type [String] sets the relationship type when creating relationships via this class
35
- def type(given_type = namespaced_model_name, auto = false)
34
+ # @param [String] given_type sets the relationship type when creating relationships via this class
35
+ # @param [Boolean] auto Should the given_type be changed in compliance with the gem's rel decorator setting?
36
+ # This option is used internally, users will usually ignore it.
37
+ def type(given_type = nil, auto = false)
38
+ return rel_type if given_type.nil?
36
39
  @rel_type = (auto ? decorated_rel_type(given_type) : given_type).tap do |type|
37
- add_wrapped_class type unless uses_classname?
40
+ add_wrapped_class(type) unless uses_classname?
38
41
  end
39
42
  end
40
43
 
@@ -49,9 +52,11 @@ module Neo4j
49
52
  end
50
53
  end
51
54
 
52
- attr_reader :rel_type
55
+ def rel_type
56
+ @rel_type || type(namespaced_model_name, true)
57
+ end
58
+
53
59
  # @return [String] a string representing the relationship type that will be created
54
- # attr_reader :rel_type
55
60
  alias_method :_type, :rel_type # Should be deprecated
56
61
 
57
62
  def add_wrapped_class(type)
@@ -0,0 +1,28 @@
1
+ module Neo4j::Shared
2
+ module Initialize
3
+ extend ActiveSupport::Concern
4
+
5
+ # Implements the Neo4j::Node#wrapper and Neo4j::Relationship#wrapper method
6
+ # so that we don't have to care if the node is wrapped or not.
7
+ # @return self
8
+ def wrapper
9
+ self
10
+ end
11
+
12
+ private
13
+
14
+ def convert_and_assign_attributes(properties)
15
+ @attributes ||= self.class.attributes_nil_hash.dup
16
+ stringify_attributes!(@attributes, properties)
17
+ self.default_properties = properties
18
+ self.class.declared_property_manager.convert_properties_to(self, :ruby, @attributes)
19
+ end
20
+
21
+ def stringify_attributes!(attr, properties)
22
+ properties.each_pair do |k, v|
23
+ key = self.class.declared_property_manager.string_key(k)
24
+ attr[key] = v
25
+ end
26
+ end
27
+ end
28
+ end
@@ -125,6 +125,13 @@ module Neo4j::Shared
125
125
 
126
126
  def_delegators :declared_property_manager, :serialized_properties, :serialized_properties=, :serialize, :declared_property_defaults
127
127
 
128
+ def inherited(other)
129
+ self.declared_property_manager.registered_properties.each_pair do |prop_key, prop_def|
130
+ other.property(prop_key, prop_def.options)
131
+ end
132
+ super
133
+ end
134
+
128
135
  # Defines a property on the class
129
136
  #
130
137
  # See active_attr gem for allowed options, e.g which type
@@ -14,5 +14,17 @@ module Neo4j::Shared
14
14
  def serializable_hash(*args)
15
15
  super.merge(id: id)
16
16
  end
17
+
18
+
19
+ module ClassMethods
20
+ def inherited(other)
21
+ inherit_serialized_properties(other) if self.respond_to?(:serialized_properties)
22
+ super
23
+ end
24
+
25
+ def inherit_serialized_properties(other)
26
+ other.serialized_properties = self.serialized_properties
27
+ end
28
+ end
17
29
  end
18
30
  end
@@ -1,3 +1,3 @@
1
1
  module Neo4j
2
- VERSION = '5.0.0'
2
+ VERSION = '5.0.1'
3
3
  end
@@ -30,7 +30,7 @@ A Neo4j OGM (Object-Graph-Mapper) for use in Ruby on Rails and Rack frameworks h
30
30
  s.add_dependency('activemodel', '~> 4')
31
31
  s.add_dependency('activesupport', '~> 4')
32
32
  s.add_dependency('active_attr', '~> 0.8')
33
- s.add_dependency('neo4j-core', '~> 5.0.0')
33
+ s.add_dependency('neo4j-core', '~> 5.0.1')
34
34
  s.add_dependency('neo4j-community', '~> 2.0') if RUBY_PLATFORM =~ /java/
35
35
  s.add_development_dependency('railties', '~> 4')
36
36
  s.add_development_dependency('pry')
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: neo4j
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.0.0
4
+ version: 5.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andreas Ronge, Brian Underwood, Chris Grigg
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-06-18 00:00:00.000000000 Z
11
+ date: 2015-06-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: orm_adapter
@@ -72,14 +72,14 @@ dependencies:
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: 5.0.0
75
+ version: 5.0.1
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: 5.0.0
82
+ version: 5.0.1
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: railties
85
85
  requirement: !ruby/object:Gem::Requirement
@@ -270,6 +270,7 @@ files:
270
270
  - lib/neo4j/shared/declared_property.rb
271
271
  - lib/neo4j/shared/declared_property_manager.rb
272
272
  - lib/neo4j/shared/identity.rb
273
+ - lib/neo4j/shared/initialize.rb
273
274
  - lib/neo4j/shared/persistence.rb
274
275
  - lib/neo4j/shared/property.rb
275
276
  - lib/neo4j/shared/rel_type_converters.rb