neo4j 5.0.0 → 5.0.1

Sign up to get free protection for your applications and to get access to all the features.
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