neo4j 4.1.5 → 5.0.0.rc.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +584 -0
- data/CONTRIBUTORS +7 -28
- data/Gemfile +6 -1
- data/README.md +54 -8
- data/lib/neo4j.rb +5 -0
- data/lib/neo4j/active_node.rb +1 -0
- data/lib/neo4j/active_node/dependent/association_methods.rb +35 -17
- data/lib/neo4j/active_node/dependent/query_proxy_methods.rb +21 -19
- data/lib/neo4j/active_node/has_n.rb +377 -132
- data/lib/neo4j/active_node/has_n/association.rb +77 -38
- data/lib/neo4j/active_node/id_property.rb +46 -28
- data/lib/neo4j/active_node/initialize.rb +18 -6
- data/lib/neo4j/active_node/labels.rb +69 -35
- data/lib/neo4j/active_node/node_wrapper.rb +37 -30
- data/lib/neo4j/active_node/orm_adapter.rb +5 -4
- data/lib/neo4j/active_node/persistence.rb +53 -10
- data/lib/neo4j/active_node/property.rb +13 -5
- data/lib/neo4j/active_node/query.rb +11 -10
- data/lib/neo4j/active_node/query/query_proxy.rb +126 -153
- data/lib/neo4j/active_node/query/query_proxy_enumerable.rb +15 -25
- data/lib/neo4j/active_node/query/query_proxy_link.rb +89 -0
- data/lib/neo4j/active_node/query/query_proxy_methods.rb +72 -19
- data/lib/neo4j/active_node/query_methods.rb +3 -1
- data/lib/neo4j/active_node/scope.rb +17 -21
- data/lib/neo4j/active_node/validations.rb +8 -2
- data/lib/neo4j/active_rel/initialize.rb +1 -2
- data/lib/neo4j/active_rel/persistence.rb +21 -33
- data/lib/neo4j/active_rel/property.rb +4 -2
- data/lib/neo4j/active_rel/types.rb +20 -8
- data/lib/neo4j/config.rb +16 -6
- data/lib/neo4j/core/query.rb +2 -2
- data/lib/neo4j/errors.rb +10 -0
- data/lib/neo4j/migration.rb +57 -46
- data/lib/neo4j/paginated.rb +3 -1
- data/lib/neo4j/railtie.rb +26 -14
- data/lib/neo4j/shared.rb +7 -1
- data/lib/neo4j/shared/declared_property.rb +62 -0
- data/lib/neo4j/shared/declared_property_manager.rb +150 -0
- data/lib/neo4j/shared/persistence.rb +15 -8
- data/lib/neo4j/shared/property.rb +64 -49
- data/lib/neo4j/shared/rel_type_converters.rb +13 -12
- data/lib/neo4j/shared/serialized_properties.rb +0 -15
- data/lib/neo4j/shared/type_converters.rb +53 -47
- data/lib/neo4j/shared/typecaster.rb +49 -0
- data/lib/neo4j/version.rb +1 -1
- data/lib/rails/generators/neo4j/model/model_generator.rb +3 -3
- data/lib/rails/generators/neo4j_generator.rb +5 -12
- data/neo4j.gemspec +4 -3
- metadata +30 -11
- data/CHANGELOG +0 -545
@@ -0,0 +1,150 @@
|
|
1
|
+
module Neo4j::Shared
|
2
|
+
# The DeclaredPropertyuManager holds details about objects created as a result of calling the #property
|
3
|
+
# class method on a class that includes Neo4j::ActiveNode or Neo4j::ActiveRel. There are many options
|
4
|
+
# that are referenced frequently, particularly during load and save, so this provides easy access and
|
5
|
+
# a way of separating behavior from the general Active{obj} modules.
|
6
|
+
#
|
7
|
+
# See Neo4j::Shared::DeclaredProperty for definitions of the property objects themselves.
|
8
|
+
class DeclaredPropertyManager
|
9
|
+
include Neo4j::Shared::TypeConverters
|
10
|
+
|
11
|
+
attr_reader :klass
|
12
|
+
|
13
|
+
# Each class that includes Neo4j::ActiveNode or Neo4j::ActiveRel gets one instance of this class.
|
14
|
+
# @param [#declared_property_manager] klass An object that has the #declared_property_manager method.
|
15
|
+
def initialize(klass)
|
16
|
+
@klass = klass
|
17
|
+
end
|
18
|
+
|
19
|
+
# @param [Neo4j::Shared::DeclaredProperty] property An instance of DeclaredProperty, created as the result of calling
|
20
|
+
# #property on an ActiveNode or ActiveRel class. The DeclaredProperty has specifics about the property, but registration
|
21
|
+
# makes the management object aware of it. This is necessary for type conversion, defaults, and inclusion in the nil and string hashes.
|
22
|
+
def register(property)
|
23
|
+
@_attributes_nil_hash = nil
|
24
|
+
@_attributes_string_map = nil
|
25
|
+
registered_properties[property.name] = property
|
26
|
+
register_magic_typecaster(property) if property.magic_typecaster
|
27
|
+
declared_property_defaults[property.name] = property.default_value if property.default_value
|
28
|
+
end
|
29
|
+
|
30
|
+
# The :default option in Neo4j::ActiveNode#property class method allows for setting a default value instead of
|
31
|
+
# nil on declared properties. This holds those values.
|
32
|
+
def declared_property_defaults
|
33
|
+
@_default_property_values ||= {}
|
34
|
+
end
|
35
|
+
|
36
|
+
def registered_properties
|
37
|
+
@_registered_properties ||= {}
|
38
|
+
end
|
39
|
+
|
40
|
+
# During object wrap, a hash is needed that contains each declared property with a nil value.
|
41
|
+
# The active_attr dependency is capable of providing this but it is expensive and calculated on the fly
|
42
|
+
# each time it is called. Rather than rely on that, we build this progressively as properties are registered.
|
43
|
+
# When the node or rel is loaded, this is used as a template.
|
44
|
+
def attributes_nil_hash
|
45
|
+
@_attributes_nil_hash ||= {}.tap do |attr_hash|
|
46
|
+
registered_properties.each_pair do |k, prop_obj|
|
47
|
+
val = prop_obj.default_value
|
48
|
+
attr_hash[k.to_s] = val
|
49
|
+
end
|
50
|
+
end.freeze
|
51
|
+
end
|
52
|
+
|
53
|
+
# During object wrapping, a props hash is built with string keys but Neo4j-core provides symbols.
|
54
|
+
# Rather than a `to_s` or `symbolize_keys` during every load, we build a map of symbol-to-string
|
55
|
+
# to speed up the process. This increases memory used by the gem but reduces object allocation and GC, so it is faster
|
56
|
+
# in practice.
|
57
|
+
def attributes_string_map
|
58
|
+
@_attributes_string_map ||= {}.tap do |attr_hash|
|
59
|
+
attributes_nil_hash.each_key { |k| attr_hash[k.to_sym] = k }
|
60
|
+
end.freeze
|
61
|
+
end
|
62
|
+
|
63
|
+
# @param [Symbol] k A symbol for which the String representation is sought. This might seem silly -- we could just call #to_s --
|
64
|
+
# but when this happens many times while loading many objects, it results in a surprisingly significant slowdown.
|
65
|
+
# The branching logic handles what happens if a property can't be found.
|
66
|
+
# The first option attempts to find it in the existing hash.
|
67
|
+
# The second option checks whether the key is the class's id property and, if it is, the string hash is rebuilt with it to prevent
|
68
|
+
# future lookups.
|
69
|
+
# The third calls `to_s`. This would happen if undeclared properties are found on the object. We could add them to the string map
|
70
|
+
# but that would result in unchecked, un-GCed memory consumption. In the event that someone is adding properties dynamically,
|
71
|
+
# maybe through user input, this would be bad.
|
72
|
+
def string_key(k)
|
73
|
+
attributes_string_map[k] || string_map_id_property(k) || k.to_s
|
74
|
+
end
|
75
|
+
|
76
|
+
def unregister(name)
|
77
|
+
# might need to be include?(name.to_s)
|
78
|
+
fail ArgumentError, "Argument `#{name}` not an attribute" if not registered_properties[name]
|
79
|
+
declared_prop = registered_properties[name]
|
80
|
+
registered_properties.delete(declared_prop)
|
81
|
+
unregister_magic_typecaster(name)
|
82
|
+
unregister_property_default(name)
|
83
|
+
end
|
84
|
+
|
85
|
+
def serialize(name, coder = JSON)
|
86
|
+
@serialize ||= {}
|
87
|
+
@serialize[name] = coder
|
88
|
+
end
|
89
|
+
|
90
|
+
def serialized_properties=(serialize_hash)
|
91
|
+
@serialized_property_keys = nil
|
92
|
+
@serialize = serialize_hash.clone
|
93
|
+
end
|
94
|
+
|
95
|
+
def serialized_properties
|
96
|
+
@serialize ||= {}
|
97
|
+
end
|
98
|
+
|
99
|
+
def serialized_properties_keys
|
100
|
+
@serialized_property_keys ||= serialized_properties.keys
|
101
|
+
end
|
102
|
+
|
103
|
+
def magic_typecast_properties_keys
|
104
|
+
@magic_typecast_properties_keys ||= magic_typecast_properties.keys
|
105
|
+
end
|
106
|
+
|
107
|
+
def magic_typecast_properties
|
108
|
+
@magic_typecast_properties ||= {}
|
109
|
+
end
|
110
|
+
|
111
|
+
# The known mappings of declared properties and their primitive types.
|
112
|
+
def upstream_primitives
|
113
|
+
@upstream_primitives ||= {}
|
114
|
+
end
|
115
|
+
|
116
|
+
protected
|
117
|
+
|
118
|
+
# Prevents repeated calls to :_attribute_type, which isn't free and never changes.
|
119
|
+
def fetch_upstream_primitive(attr)
|
120
|
+
upstream_primitives[attr] || upstream_primitives[attr] = klass._attribute_type(attr)
|
121
|
+
end
|
122
|
+
|
123
|
+
private
|
124
|
+
|
125
|
+
# @param [Symbol] key An undeclared property value found in the _persisted_obj.props hash.
|
126
|
+
# Typically, this is a node's id property, which will not be registered as other properties are.
|
127
|
+
# In the future, this should probably be reworked a bit. This class should either not know or care
|
128
|
+
# about the id property or it should be in charge of it. In the meantime, this improves
|
129
|
+
# node load performance.
|
130
|
+
def string_map_id_property(key)
|
131
|
+
return unless klass.id_property_name == key
|
132
|
+
@_attributes_string_map = attributes_string_map.dup.tap { |h| h[key] = key.to_s }.freeze
|
133
|
+
end
|
134
|
+
|
135
|
+
def unregister_magic_typecaster(property)
|
136
|
+
magic_typecast_properties.delete(property)
|
137
|
+
@magic_typecast_properties_keys = nil
|
138
|
+
end
|
139
|
+
|
140
|
+
def unregister_property_default(property)
|
141
|
+
declared_property_defaults.delete(property)
|
142
|
+
@_default_property_values = nil
|
143
|
+
end
|
144
|
+
|
145
|
+
def register_magic_typecaster(property)
|
146
|
+
magic_typecast_properties[property.name] = property.magic_typecaster
|
147
|
+
@magic_typecast_properties_keys = nil
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
@@ -1,17 +1,16 @@
|
|
1
1
|
module Neo4j::Shared
|
2
2
|
module Persistence
|
3
3
|
extend ActiveSupport::Concern
|
4
|
-
include Neo4j::Shared::TypeConverters
|
5
4
|
|
6
5
|
USES_CLASSNAME = []
|
7
6
|
|
8
7
|
def update_model
|
9
|
-
if changed_attributes
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
8
|
+
return if !changed_attributes || changed_attributes.empty?
|
9
|
+
|
10
|
+
changed_props = attributes.select { |k, _| changed_attributes.include?(k) }
|
11
|
+
changed_props = self.class.declared_property_manager.convert_properties_to(self, :db, changed_props)
|
12
|
+
_persisted_obj.update_props(changed_props)
|
13
|
+
changed_attributes.clear
|
15
14
|
end
|
16
15
|
|
17
16
|
# Convenience method to set attribute and #save at the same time
|
@@ -33,6 +32,7 @@ module Neo4j::Shared
|
|
33
32
|
def create_or_update
|
34
33
|
# since the same model can be created or updated twice from a relationship we have to have this guard
|
35
34
|
@_create_or_updating = true
|
35
|
+
apply_default_values
|
36
36
|
result = _persisted_obj ? update_model : create_model
|
37
37
|
if result == false
|
38
38
|
Neo4j::Transaction.current.failure if Neo4j::Transaction.current
|
@@ -47,6 +47,13 @@ module Neo4j::Shared
|
|
47
47
|
@_create_or_updating = nil
|
48
48
|
end
|
49
49
|
|
50
|
+
def apply_default_values
|
51
|
+
return if self.class.declared_property_defaults.empty?
|
52
|
+
self.class.declared_property_defaults.each_pair do |key, value|
|
53
|
+
self.send("#{key}=", value) if self.send(key).nil?
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
50
57
|
# Returns +true+ if the record is persisted, i.e. it's not a new record and it was not destroyed
|
51
58
|
def persisted?
|
52
59
|
!new_record? && !destroyed?
|
@@ -92,7 +99,7 @@ module Neo4j::Shared
|
|
92
99
|
|
93
100
|
def reload
|
94
101
|
return self if new_record?
|
95
|
-
|
102
|
+
association_proxy_cache.clear
|
96
103
|
changed_attributes && changed_attributes.clear
|
97
104
|
unless reload_from_database
|
98
105
|
@_deleted = true
|
@@ -11,22 +11,21 @@ module Neo4j::Shared
|
|
11
11
|
|
12
12
|
class UndefinedPropertyError < RuntimeError; end
|
13
13
|
class MultiparameterAssignmentError < StandardError; end
|
14
|
-
|
15
|
-
|
16
|
-
ILLEGAL_PROPS = %w(from_node to_node start_node end_node)
|
14
|
+
# @_declared_property_manager = DeclaredPropertyManager.new
|
17
15
|
|
18
16
|
attr_reader :_persisted_obj
|
19
17
|
|
20
|
-
|
21
|
-
|
18
|
+
# TODO: Remove the commented :super entirely once this code is part of a release.
|
19
|
+
# It calls an init method in active_attr that has a very negative impact on performance.
|
20
|
+
def initialize(attributes = {}, _options = nil)
|
21
|
+
attributes = process_attributes(attributes) unless attributes.empty?
|
22
22
|
@relationship_props = self.class.extract_association_attributes!(attributes)
|
23
23
|
writer_method_props = extract_writer_methods!(attributes)
|
24
24
|
validate_attributes!(attributes)
|
25
|
-
send_props(writer_method_props) unless writer_method_props.
|
25
|
+
send_props(writer_method_props) unless writer_method_props.empty?
|
26
26
|
|
27
27
|
@_persisted_obj = nil
|
28
|
-
|
29
|
-
super(attributes, options)
|
28
|
+
# super(attributes, options)
|
30
29
|
end
|
31
30
|
|
32
31
|
# Returning nil when we get ActiveAttr::UnknownAttributeError from ActiveAttr
|
@@ -38,8 +37,8 @@ module Neo4j::Shared
|
|
38
37
|
alias_method :[], :read_attribute
|
39
38
|
|
40
39
|
def default_properties=(properties)
|
41
|
-
|
42
|
-
@default_properties = properties.select { |key|
|
40
|
+
default_property_keys = self.class.default_properties_keys
|
41
|
+
@default_properties = properties.select { |key| default_property_keys.include?(key) }
|
43
42
|
end
|
44
43
|
|
45
44
|
def default_property(key)
|
@@ -53,9 +52,17 @@ module Neo4j::Shared
|
|
53
52
|
end
|
54
53
|
|
55
54
|
def send_props(hash)
|
56
|
-
hash.each
|
57
|
-
|
58
|
-
|
55
|
+
hash.each { |key, value| self.send("#{key}=", value) }
|
56
|
+
end
|
57
|
+
|
58
|
+
protected
|
59
|
+
|
60
|
+
# This method is defined in ActiveModel.
|
61
|
+
# When each node is loaded, it is called once in pursuit of 'sanitize_for_mass_assignment', which this gem does not implement.
|
62
|
+
# In the course of doing that, it calls :attributes, which is quite expensive, so we return immediately.
|
63
|
+
def attribute_method?(attr_name) #:nodoc:
|
64
|
+
return false if attr_name == 'sanitize_for_mass_assignment'
|
65
|
+
super(attr_name)
|
59
66
|
end
|
60
67
|
|
61
68
|
private
|
@@ -63,13 +70,17 @@ module Neo4j::Shared
|
|
63
70
|
# Changes attributes hash to remove relationship keys
|
64
71
|
# Raises an error if there are any keys left which haven't been defined as properties on the model
|
65
72
|
def validate_attributes!(attributes)
|
73
|
+
return attributes if attributes.empty?
|
66
74
|
invalid_properties = attributes.keys.map(&:to_s) - self.attributes.keys
|
67
75
|
fail UndefinedPropertyError, "Undefined properties: #{invalid_properties.join(',')}" if invalid_properties.size > 0
|
68
76
|
end
|
69
77
|
|
70
78
|
def extract_writer_methods!(attributes)
|
71
|
-
attributes
|
72
|
-
|
79
|
+
return attributes if attributes.empty?
|
80
|
+
{}.tap do |writer_method_props|
|
81
|
+
attributes.each_key do |key|
|
82
|
+
writer_method_props[key] = attributes.delete(key) if self.respond_to?("#{key}=")
|
83
|
+
end
|
73
84
|
end
|
74
85
|
end
|
75
86
|
|
@@ -78,8 +89,9 @@ module Neo4j::Shared
|
|
78
89
|
multi_parameter_attributes = {}
|
79
90
|
new_attributes = {}
|
80
91
|
attributes.each_pair do |key, value|
|
81
|
-
if
|
82
|
-
found_key
|
92
|
+
if match = key.match(/\A([^\(]+)\((\d+)([if])\)$/)
|
93
|
+
found_key = match[1]
|
94
|
+
index = match[2].to_i
|
83
95
|
(multi_parameter_attributes[found_key] ||= {})[index] = value.empty? ? nil : value.send("to_#{$3}")
|
84
96
|
else
|
85
97
|
new_attributes[key] = value
|
@@ -90,16 +102,15 @@ module Neo4j::Shared
|
|
90
102
|
end
|
91
103
|
|
92
104
|
def process_multiparameter_attributes(multi_parameter_attributes, new_attributes)
|
93
|
-
multi_parameter_attributes.
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
rescue
|
99
|
-
raise MultiparameterAssignmentError, "error on assignment #{values.inspect} to #{key}"
|
105
|
+
multi_parameter_attributes.each_with_object(new_attributes) do |(key, values), attributes|
|
106
|
+
values = (values.keys.min..values.keys.max).map { |i| values[i] }
|
107
|
+
|
108
|
+
if (field = self.class.attributes[key.to_sym]).nil?
|
109
|
+
fail MultiparameterAssignmentError, "error on assignment #{values.inspect} to #{key}"
|
100
110
|
end
|
111
|
+
|
112
|
+
attributes[key] = instantiate_object(field, values)
|
101
113
|
end
|
102
|
-
new_attributes
|
103
114
|
end
|
104
115
|
|
105
116
|
def instantiate_object(field, values_with_empty_parameters)
|
@@ -110,6 +121,10 @@ module Neo4j::Shared
|
|
110
121
|
end
|
111
122
|
|
112
123
|
module ClassMethods
|
124
|
+
extend Forwardable
|
125
|
+
|
126
|
+
def_delegators :declared_property_manager, :serialized_properties, :serialized_properties=, :serialize, :declared_property_defaults
|
127
|
+
|
113
128
|
# Defines a property on the class
|
114
129
|
#
|
115
130
|
# See active_attr gem for allowed options, e.g which type
|
@@ -139,22 +154,25 @@ module Neo4j::Shared
|
|
139
154
|
# property :name, constraint: :unique
|
140
155
|
# end
|
141
156
|
def property(name, options = {})
|
142
|
-
|
143
|
-
|
144
|
-
|
157
|
+
prop = DeclaredProperty.new(name, options)
|
158
|
+
prop.register
|
159
|
+
declared_property_manager.register(prop)
|
160
|
+
|
161
|
+
attribute(name, prop.options)
|
145
162
|
constraint_or_index(name, options)
|
146
163
|
end
|
147
164
|
|
148
165
|
def undef_property(name)
|
149
|
-
|
150
|
-
|
151
|
-
attribute_methods(name).each do |method|
|
152
|
-
undef_method(method)
|
153
|
-
end
|
154
|
-
|
166
|
+
declared_property_manager.unregister(name)
|
167
|
+
attribute_methods(name).each { |method| undef_method(method) }
|
155
168
|
undef_constraint_or_index(name)
|
156
169
|
end
|
157
170
|
|
171
|
+
def declared_property_manager
|
172
|
+
@_declared_property_manager ||= DeclaredPropertyManager.new(self)
|
173
|
+
end
|
174
|
+
|
175
|
+
# TODO: Move this to the DeclaredPropertyManager
|
158
176
|
def default_property(name, &block)
|
159
177
|
reset_default_properties(name) if default_properties.respond_to?(:size)
|
160
178
|
default_properties[name] = block
|
@@ -165,10 +183,16 @@ module Neo4j::Shared
|
|
165
183
|
@default_property ||= {}
|
166
184
|
end
|
167
185
|
|
186
|
+
def default_properties_keys
|
187
|
+
@default_properties_keys ||= default_properties.keys
|
188
|
+
end
|
189
|
+
|
168
190
|
def reset_default_properties(name_to_keep)
|
169
191
|
default_properties.each_key do |property|
|
192
|
+
@default_properties_keys = nil
|
170
193
|
undef_method(property) unless property == name_to_keep
|
171
194
|
end
|
195
|
+
@default_properties_keys = nil
|
172
196
|
@default_property = {}
|
173
197
|
end
|
174
198
|
|
@@ -187,6 +211,12 @@ module Neo4j::Shared
|
|
187
211
|
end
|
188
212
|
end
|
189
213
|
|
214
|
+
# @return [Hash] A frozen hash of all model properties with nil values. It is used during node loading and prevents
|
215
|
+
# an extra call to a slow dependency method.
|
216
|
+
def attributes_nil_hash
|
217
|
+
declared_property_manager.attributes_nil_hash
|
218
|
+
end
|
219
|
+
|
190
220
|
private
|
191
221
|
|
192
222
|
def constraint_or_index(name, options)
|
@@ -199,21 +229,6 @@ module Neo4j::Shared
|
|
199
229
|
index(name, options) if options[:index] == :exact
|
200
230
|
end
|
201
231
|
end
|
202
|
-
|
203
|
-
def check_illegal_prop(name)
|
204
|
-
if ILLEGAL_PROPS.include?(name.to_s)
|
205
|
-
fail IllegalPropertyError, "#{name} is an illegal property"
|
206
|
-
end
|
207
|
-
end
|
208
|
-
|
209
|
-
# Tweaks properties
|
210
|
-
def magic_properties(name, options)
|
211
|
-
options[:type] ||= DateTime if name.to_sym == :created_at || name.to_sym == :updated_at
|
212
|
-
|
213
|
-
# ActiveAttr does not handle "Time", Rails and Neo4j.rb 2.3 did
|
214
|
-
# Convert it to DateTime in the interest of consistency
|
215
|
-
options[:type] = DateTime if options[:type] == Time
|
216
|
-
end
|
217
232
|
end
|
218
233
|
end
|
219
234
|
end
|
@@ -24,18 +24,19 @@ module Neo4j::Shared
|
|
24
24
|
# @return [String] A string that conforms to the set rel type conversion setting.
|
25
25
|
def decorated_rel_type(type)
|
26
26
|
type = type.to_s
|
27
|
-
case rel_transformer
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
27
|
+
decorated_type = case rel_transformer
|
28
|
+
when :upcase
|
29
|
+
type.underscore.upcase
|
30
|
+
when :downcase
|
31
|
+
type.underscore.downcase
|
32
|
+
when :legacy
|
33
|
+
"##{type.underscore.downcase}"
|
34
|
+
when :none
|
35
|
+
type
|
36
|
+
else
|
37
|
+
type.underscore.upcase
|
38
|
+
end
|
39
|
+
decorated_type.tap { |s| s.gsub!('/', '::') if type.include?('::') }
|
39
40
|
end
|
40
41
|
end
|
41
42
|
end
|
@@ -14,20 +14,5 @@ module Neo4j::Shared
|
|
14
14
|
def serializable_hash(*args)
|
15
15
|
super.merge(id: id)
|
16
16
|
end
|
17
|
-
|
18
|
-
module ClassMethods
|
19
|
-
def serialized_properties
|
20
|
-
@serialize || {}
|
21
|
-
end
|
22
|
-
|
23
|
-
def serialized_properties=(serialize_hash)
|
24
|
-
@serialize = serialize_hash.clone
|
25
|
-
end
|
26
|
-
|
27
|
-
def serialize(name, coder = JSON)
|
28
|
-
@serialize ||= {}
|
29
|
-
@serialize[name] = coder
|
30
|
-
end
|
31
|
-
end
|
32
17
|
end
|
33
18
|
end
|