neo4j 6.0.0.alpha.11 → 6.0.0.alpha.12
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 +4 -4
- data/CHANGELOG.md +8 -0
- data/lib/neo4j/active_node.rb +5 -0
- data/lib/neo4j/active_node/has_n/association.rb +0 -6
- data/lib/neo4j/active_node/node_wrapper.rb +1 -7
- data/lib/neo4j/active_node/persistence.rb +1 -2
- data/lib/neo4j/active_node/query/query_proxy.rb +1 -3
- data/lib/neo4j/active_rel.rb +22 -1
- data/lib/neo4j/active_rel/rel_wrapper.rb +1 -5
- data/lib/neo4j/active_rel/related_node.rb +1 -1
- data/lib/neo4j/active_rel/types.rb +1 -4
- data/lib/neo4j/config.rb +0 -4
- data/lib/neo4j/migration.rb +0 -92
- data/lib/neo4j/shared/persistence.rb +0 -49
- data/lib/neo4j/shared/property.rb +3 -2
- data/lib/neo4j/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 88d57fe8f616166912b89e008686fea6190fee43
|
4
|
+
data.tar.gz: 83cbc8c78c8ae3a8571ed0870699f0537b018a84
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
data/lib/neo4j/active_node.rb
CHANGED
@@ -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
|
-
|
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)
|
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.
|
222
|
+
association.relationship_class.create(properties.merge(node_props))
|
225
223
|
end
|
226
224
|
end
|
227
225
|
|
data/lib/neo4j/active_rel.rb
CHANGED
@@ -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
|
-
|
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 =
|
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
|
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)
|
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]
|
data/lib/neo4j/migration.rb
CHANGED
@@ -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
|
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
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.
|
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-
|
11
|
+
date: 2015-11-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: orm_adapter
|