neo4j 6.0.0.alpha.11 → 6.0.0.alpha.12

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: cbd147ccfe5710b9dd99035774e8ccac71f1a2fe
4
- data.tar.gz: 0afb13bbc63f47ce1658313f13541586cdbaca8b
3
+ metadata.gz: 88d57fe8f616166912b89e008686fea6190fee43
4
+ data.tar.gz: 83cbc8c78c8ae3a8571ed0870699f0537b018a84
5
5
  SHA512:
6
- metadata.gz: ba9b1a7bed89c5e0d3be9349a527b496d0cd92a025b0602e68a89b38e4bcae5e45de4a667249abeb23c7fa63be7fcf26f152e48b117108eebcb6f38fe061729c
7
- data.tar.gz: ccb77857f67f3bc4ac45087b10d71ef2117b6170ed437aae1593a77f4ff35549a709b76d9046430dd429419efc6cb829cd76e80e1e790b5faad49a454e6d88dd
6
+ metadata.gz: c13bb99309098ea662883902a7491cec10d32c9beb475a96825622e0a3b9e2f032b6d92eed15524613a796ab00da7407516241f5d655c1fc770ee1e0a321f70e
7
+ data.tar.gz: db933033b16e28f6282dd3e6b46f772587bfa670d125c26e2289f32bba771d93c66c5da3933fe1beb0fab1783495af1604c82ba616179f78179b4f2889a1a55e
data/CHANGELOG.md CHANGED
@@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file.
3
3
  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.0.0.alpha.12] - 11-5-2015
7
+
8
+ ### Changed
9
+ - `_classname` property has been completely removed, officially dropping support for Neo4j < 2.1.5.
10
+
11
+ ### Added
12
+ - Optional three-argument signature for `ActiveRel#create` and `#create!`, just like `initialize`.
13
+
6
14
  ## [6.0.0.alpha.11] - 11-3-2015
7
15
 
8
16
  ### Fixed
@@ -41,6 +41,11 @@ module Neo4j
41
41
  include Neo4j::ActiveNode::Scope
42
42
  include Neo4j::ActiveNode::Dependent
43
43
 
44
+ def initialize(args = nil)
45
+ symbol_args = args.is_a?(Hash) ? args.symbolize_keys : args
46
+ super(symbol_args)
47
+ end
48
+
44
49
  def neo4j_obj
45
50
  _persisted_obj || fail('Tried to access native neo4j object on a non persisted object')
46
51
  end
@@ -128,12 +128,6 @@ module Neo4j
128
128
  @relationship_class ||= @relationship_class_name && @relationship_class_name.constantize
129
129
  end
130
130
 
131
- def inject_classname(properties)
132
- return properties unless relationship_class
133
- properties[Neo4j::Config.class_name_property] = relationship_class_name if relationship_class.cached_class?(true)
134
- properties
135
- end
136
-
137
131
  def unique?
138
132
  return relationship_class.unique? if rel_class?
139
133
  @origin ? origin_association.unique? : !!@unique
@@ -15,7 +15,7 @@ class Neo4j::Node
15
15
 
16
16
  def class_to_wrap
17
17
  load_classes_from_labels
18
- (named_class || ::Neo4j::ActiveNode::Labels.model_for_labels(labels)).tap do |model_class|
18
+ Neo4j::ActiveNode::Labels.model_for_labels(labels).tap do |model_class|
19
19
  Neo4j::Node::Wrapper.populate_constants_for_labels_cache(model_class, labels)
20
20
  end
21
21
  end
@@ -48,11 +48,5 @@ class Neo4j::Node
48
48
  def self.association_model_namespace
49
49
  Neo4j::Config.association_model_namespace_string
50
50
  end
51
-
52
- def named_class
53
- property = Neo4j::Config.class_name_property
54
-
55
- Neo4j::Node::Wrapper.constant_for_label(self.props[property]) if self.props.is_a?(Hash) && self.props.key?(property)
56
- end
57
51
  end
58
52
  end
@@ -130,9 +130,8 @@ module Neo4j::ActiveNode
130
130
 
131
131
  def find_or_create(find_attributes, set_attributes = {})
132
132
  on_create_attributes = set_attributes.merge(on_create_props(find_attributes))
133
- on_match_attributes = set_attributes.merge(on_match_props)
134
133
  neo4j_session.query.merge(n: {self.mapped_label_names => find_attributes})
135
- .on_create_set(n: on_create_attributes).on_match_set(n: on_match_attributes)
134
+ .on_create_set(n: on_create_attributes)
136
135
  .pluck(:n).first
137
136
  end
138
137
 
@@ -178,8 +178,6 @@ module Neo4j
178
178
  fail 'Can only create relationships on associations' if !@association
179
179
  other_nodes = _nodeify!(*other_nodes)
180
180
 
181
- properties = @association.inject_classname(properties)
182
-
183
181
  Neo4j::Transaction.run do
184
182
  other_nodes.each do |other_node|
185
183
  other_node.save unless other_node.neo_id
@@ -221,7 +219,7 @@ module Neo4j
221
219
  Array(other_node_or_nodes).each do |other_node|
222
220
  node_props = (association.direction == :in) ? {from_node: other_node, to_node: @start_object} : {from_node: @start_object, to_node: other_node}
223
221
 
224
- association.relationship_class.create(properties.except(:_classname).merge(node_props))
222
+ association.relationship_class.create(properties.merge(node_props))
225
223
  end
226
224
  end
227
225
 
@@ -19,7 +19,9 @@ module Neo4j
19
19
 
20
20
  def initialize(from_node = nil, to_node = nil, args = nil)
21
21
  load_nodes(node_or_nil(from_node), node_or_nil(to_node))
22
- super(hash_or_nil(from_node, args))
22
+ resolved_args = hash_or_nil(from_node, args)
23
+ symbol_args = resolved_args.is_a?(Hash) ? resolved_args.symbolize_keys : resolved_args
24
+ super(symbol_args)
23
25
  end
24
26
 
25
27
  def node_cypher_representation(node)
@@ -53,5 +55,24 @@ module Neo4j
53
55
  def hash_or_nil(node_or_hash, hash_or_nil)
54
56
  node_or_hash.is_a?(Hash) ? node_or_hash : hash_or_nil
55
57
  end
58
+
59
+ module ClassMethods
60
+ [:create, :create!].each do |meth|
61
+ define_method(meth) do |from_node_or_args = nil, to_node = nil, args = nil|
62
+ return super(from_node_or_args) if from_node_or_args.is_a?(Hash)
63
+ args_hash = args || {}
64
+ args_with_node!(:from_node, from_node_or_args, args_hash)
65
+ args_with_node!(:to_node, to_node, args_hash)
66
+ super(args_hash)
67
+ end
68
+ end
69
+
70
+ private
71
+
72
+ def args_with_node!(key, node, args)
73
+ args[key] = node if node.is_a?(Neo4j::ActiveNode)
74
+ args
75
+ end
76
+ end
56
77
  end
57
78
  end
@@ -3,7 +3,7 @@ class Neo4j::Relationship
3
3
  def wrapper
4
4
  props.symbolize_keys!
5
5
  begin
6
- most_concrete_class = sorted_wrapper_classes
6
+ most_concrete_class = class_from_type
7
7
  wrapped_rel = most_concrete_class.constantize.new
8
8
  rescue NameError
9
9
  return self
@@ -15,10 +15,6 @@ class Neo4j::Relationship
15
15
 
16
16
  private
17
17
 
18
- def sorted_wrapper_classes
19
- props[Neo4j::Config.class_name_property] || class_from_type
20
- end
21
-
22
18
  def class_from_type
23
19
  Neo4j::ActiveRel::Types::WRAPPED_CLASSES[rel_type] || Neo4j::ActiveRel::Types::WRAPPED_CLASSES[rel_type] = rel_type.camelize
24
20
  end
@@ -29,7 +29,7 @@ module Neo4j::ActiveRel
29
29
 
30
30
  # Loads a node from the database or returns the node if already laoded
31
31
  def loaded
32
- fail NilRelatedNodeError, 'Node not set, cannot load' if @node.nil?
32
+ fail UnsetRelatedNodeError, 'Node not set, cannot load' if @node.nil?
33
33
  @node = @node.respond_to?(:neo_id) ? @node : Neo4j::Node.load(@node)
34
34
  end
35
35
 
@@ -15,9 +15,6 @@ module Neo4j
15
15
  #
16
16
  # A model is added to WRAPPED_CLASSES when it is initalized AND when the `type` class method is called within a model. This means that
17
17
  # it's possible a model will be added twice: once with the rel_type version of the model name, again with the custom type. deal_with_it.gif.
18
- #
19
- # As an alternative to this, you can call the `set_classname` class method to insert a `_classname` property into your relationship,
20
- # which will completely bypass this whole process.
21
18
  WRAPPED_CLASSES = {}
22
19
 
23
20
  included do
@@ -76,7 +73,7 @@ module Neo4j
76
73
 
77
74
  def assign_type!(given_type, auto)
78
75
  @rel_type = (auto ? decorated_rel_type(given_type) : given_type).tap do |type|
79
- add_wrapped_class(type) unless uses_classname?
76
+ add_wrapped_class(type)
80
77
  end
81
78
  end
82
79
  end
data/lib/neo4j/config.rb CHANGED
@@ -96,10 +96,6 @@ module Neo4j
96
96
  configuration.to_yaml
97
97
  end
98
98
 
99
- def class_name_property
100
- @_class_name_property = Neo4j::Config[CLASS_NAME_PROPERTY_KEY] || :_classname
101
- end
102
-
103
99
  def include_root_in_json
104
100
  # we use ternary because a simple || will always evaluate true
105
101
  Neo4j::Config[:include_root_in_json].nil? ? true : Neo4j::Config[:include_root_in_json]
@@ -123,97 +123,5 @@ MESSAGE
123
123
  end
124
124
  end
125
125
  end
126
-
127
- class AddClassnames < Neo4j::Migration
128
- def initialize(path = default_path)
129
- @classnames_filename = 'add_classnames.yml'
130
- @classnames_filepath = File.join(joined_path(path), classnames_filename)
131
- end
132
-
133
- def migrate
134
- output 'Adding classnames. This make take some time.'
135
- execute(true)
136
- end
137
-
138
- def test
139
- output 'TESTING! No queries will be executed.'
140
- execute(false)
141
- end
142
-
143
- def setup
144
- output "Creating file #{classnames_filepath}. Please use this as the migration guide."
145
- FileUtils.mkdir_p('db/neo4j-migrate')
146
-
147
- return if File.file?(classnames_filepath)
148
-
149
- source = File.join(File.dirname(__FILE__), '..', '..', 'config', 'neo4j', classnames_filename)
150
- FileUtils.copy_file(source, classnames_filepath)
151
- end
152
-
153
- private
154
-
155
- attr_reader :classnames_filename, :classnames_filepath, :model_map
156
-
157
- def execute(migrate = false)
158
- file_init
159
- map = []
160
- map.push :nodes if model_map[:nodes]
161
- map.push :relationships if model_map[:relationships]
162
- map.each do |type|
163
- model_map[type].each do |action, labels|
164
- do_classnames(action, labels, type, migrate)
165
- end
166
- end
167
- end
168
-
169
- def do_classnames(action, labels, type, migrate = false)
170
- method = type == :nodes ? :node_cypher : :rel_cypher
171
- labels.each do |label|
172
- output cypher = self.send(method, label, action)
173
- execute_cypher(cypher) if migrate
174
- end
175
- end
176
-
177
- def file_init
178
- @model_map = ActiveSupport::HashWithIndifferentAccess.new(YAML.load_file(classnames_filepath))
179
- end
180
-
181
- def node_cypher(label, action)
182
- where, phrase_start = action_variables(action, 'n')
183
- output "#{phrase_start} _classname '#{label}' on nodes with matching label:"
184
- "MATCH (n:`#{label}`) #{where} SET n._classname = '#{label}' RETURN COUNT(n) as modified"
185
- end
186
-
187
- def rel_cypher(hash, action)
188
- label = hash[0]
189
- value = hash[1]
190
- from = value[:from]
191
- fail "All relationships require a 'type'" unless value[:type]
192
-
193
- from_cypher = from ? "(from:`#{from}`)" : '(from)'
194
- to = value[:to]
195
- to_cypher = to ? "(to:`#{to}`)" : '(to)'
196
- type = "[r:`#{value[:type]}`]"
197
- where, phrase_start = action_variables(action, 'r')
198
- output "#{phrase_start} _classname '#{label}' where type is '#{value[:type]}' using cypher:"
199
- "MATCH #{from_cypher}-#{type}->#{to_cypher} #{where} SET r._classname = '#{label}' return COUNT(r) as modified"
200
- end
201
-
202
- def execute_cypher(query_string)
203
- output "Modified #{Neo4j::Session.query(query_string).first.modified} records"
204
- output ''
205
- end
206
-
207
- def action_variables(action, identifier)
208
- case action
209
- when 'overwrite'
210
- ['', 'Overwriting']
211
- when 'add'
212
- ["WHERE NOT HAS(#{identifier}._classname)", 'Adding']
213
- else
214
- fail "Invalid action #{action} specified"
215
- end
216
- end
217
- end
218
126
  end
219
127
  end
@@ -2,8 +2,6 @@ module Neo4j::Shared
2
2
  module Persistence
3
3
  extend ActiveSupport::Concern
4
4
 
5
- USES_CLASSNAME = []
6
-
7
5
  # @return [Hash] Given a node's state, will call the appropriate `props_for_{action}` method.
8
6
  def props_for_persistence
9
7
  _persisted_obj ? props_for_update : props_for_create
@@ -18,7 +16,6 @@ module Neo4j::Shared
18
16
  # Returns a hash containing:
19
17
  # * All properties and values for insertion in the database
20
18
  # * A `uuid` (or equivalent) key and value
21
- # * A `_classname` property, if one is to be set
22
19
  # * Timestamps, if the class is set to include them.
23
20
  # Note that the UUID is added to the hash but is not set on the node.
24
21
  # The timestamps, by comparison, are set on the node prior to addition in this hash.
@@ -27,7 +24,6 @@ module Neo4j::Shared
27
24
  inject_timestamps!
28
25
  props_with_defaults = inject_defaults!(props)
29
26
  converted_props = props_for_db(props_with_defaults)
30
- inject_classname!(converted_props)
31
27
  return converted_props unless self.class.respond_to?(:default_property_values)
32
28
  inject_primary_key!(converted_props)
33
29
  end
@@ -187,61 +183,16 @@ module Neo4j::Shared
187
183
  self.updated_at = DateTime.now if respond_to?(:updated_at=) && (updated_at.nil? || (changed? && !updated_at_changed?))
188
184
  end
189
185
 
190
- # Inserts the _classname property into an object's properties during object creation.
191
- def inject_classname!(props, check_version = true)
192
- props[:_classname] = self.class.name if self.class.cached_class?(check_version)
193
- end
194
-
195
- def set_classname(props, check_version = true)
196
- warning = 'This method has been replaced with `inject_classname!` and will be removed in a future version'.freeze
197
- ActiveSupport::Deprecation.warn warning, caller
198
- inject_classname!(props, check_version)
199
- end
200
-
201
186
  def inject_timestamps!
202
187
  now = DateTime.now
203
188
  self.created_at ||= now if respond_to?(:created_at=)
204
189
  self.updated_at ||= now if respond_to?(:updated_at=)
205
190
  end
206
191
 
207
-
208
-
209
192
  def set_timestamps
210
193
  warning = 'This method has been replaced with `inject_timestamps!` and will be removed in a future version'.freeze
211
194
  ActiveSupport::Deprecation.warn warning, caller
212
195
  inject_timestamps!
213
196
  end
214
-
215
- module ClassMethods
216
- # Determines whether a model should insert a _classname property. This can be used to override the automatic matching of returned
217
- # objects to models.
218
- def cached_class?(check_version = true)
219
- uses_classname? || (!!Neo4j::Config[:cache_class_names] && (check_version ? neo4j_session.version < '2.1.5' : true))
220
- end
221
-
222
- # @return [Boolean] status of whether this model will add a _classname property
223
- def uses_classname?
224
- Neo4j::Shared::Persistence::USES_CLASSNAME.include?(self.name)
225
- end
226
-
227
- # Adds this model to the USES_CLASSNAME array. When new rels/nodes are created, a _classname property will be added. This will override the
228
- # automatic matching of label/rel type to model.
229
- #
230
- # You'd want to do this if you have multiple models for the same label or relationship type. When it comes to labels, there isn't really any
231
- # reason to do this because you can have multiple labels; on the other hand, an argument can be made for doing this with relationships since
232
- # rel type is a bit more restrictive.
233
- #
234
- # It could also be speculated that there's a slight performance boost to using _classname since the gem immediately knows what model is responsible
235
- # for a returned object. At the same time, it is a bit restrictive and changing it can be a bit of a PITA. Use carefully!
236
- def set_classname
237
- Neo4j::Shared::Persistence::USES_CLASSNAME << self.name
238
- end
239
-
240
- # Removes this model from the USES_CLASSNAME array. When new rels/nodes are create, no _classname property will be injected. Upon returning of
241
- # the object from the database, it will be matched to a model using its relationship type or labels.
242
- def unset_classname
243
- Neo4j::Shared::Persistence::USES_CLASSNAME.delete self.name
244
- end
245
- end
246
197
  end
247
198
  end
@@ -84,13 +84,15 @@ module Neo4j::Shared
84
84
  end
85
85
  end
86
86
 
87
+ DATE_KEY_REGEX = /\A([^\(]+)\((\d+)([if])\)$/
87
88
  # Gives support for Rails date_select, datetime_select, time_select helpers.
88
89
  def process_attributes(attributes = nil)
89
90
  return attributes if attributes.blank?
90
91
  multi_parameter_attributes = {}
91
92
  new_attributes = {}
92
93
  attributes.each_pair do |key, value|
93
- if match = key.match(/\A([^\(]+)\((\d+)([if])\)$/)
94
+ if key.match(DATE_KEY_REGEX)
95
+ match = key.to_s.match(DATE_KEY_REGEX)
94
96
  found_key = match[1]
95
97
  index = match[2].to_i
96
98
  (multi_parameter_attributes[found_key] ||= {})[index] = value.empty? ? nil : value.send("to_#{$3}")
@@ -105,7 +107,6 @@ module Neo4j::Shared
105
107
  def process_multiparameter_attributes(multi_parameter_attributes, new_attributes)
106
108
  multi_parameter_attributes.each_with_object(new_attributes) do |(key, values), attributes|
107
109
  values = (values.keys.min..values.keys.max).map { |i| values[i] }
108
-
109
110
  if (field = self.class.attributes[key.to_sym]).nil?
110
111
  fail MultiparameterAssignmentError, "error on assignment #{values.inspect} to #{key}"
111
112
  end
data/lib/neo4j/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Neo4j
2
- VERSION = '6.0.0.alpha.11'
2
+ VERSION = '6.0.0.alpha.12'
3
3
  end
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: 6.0.0.alpha.11
4
+ version: 6.0.0.alpha.12
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-11-03 00:00:00.000000000 Z
11
+ date: 2015-11-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: orm_adapter