Class: ActiveGraph::Shared::DeclaredProperties
- Inherits:
-
Object
- Object
- ActiveGraph::Shared::DeclaredProperties
show all
- Includes:
- TypeConverters
- Defined in:
- lib/active_graph/shared/declared_properties.rb
Overview
The DeclaredPropertyuManager holds details about objects created as a result of calling the #property class method on a class that includes ActiveGraph::Node or ActiveGraph::Relationship. There are many options that are referenced frequently, particularly during load and save, so this provides easy access and a way of separating behavior from the general Activeobj modules.
See ActiveGraph::Shared::DeclaredProperty for definitions of the property objects themselves.
Constant Summary
collapse
- EXCLUDED_TYPES =
[Array, Range, Regexp]
TypeConverters::CONVERTERS
Instance Attribute Summary collapse
Instance Method Summary
collapse
-
#[](key) ⇒ Object
-
#attributes_nil_hash ⇒ Object
During object wrap, a hash is needed that contains each declared property with a nil value.
-
#attributes_string_map ⇒ Object
During object wrapping, a props hash is built with string keys but ActiveGraph::Core provides symbols.
-
#constraint_or_fail!(key, id_property_name, type = :unique) ⇒ Object
-
#declared_property_defaults ⇒ Object
The :default option in ActiveGraph::Node#property class method allows for setting a default value instead of nil on declared properties.
-
#index_or_fail!(key, id_property_name, type = :exact) ⇒ Object
-
#indexed_properties ⇒ Object
-
#initialize(klass) ⇒ DeclaredProperties
constructor
Each class that includes ActiveGraph::Node or ActiveGraph::Relationship gets one instance of this class.
-
#inject_defaults!(object, props) ⇒ Object
-
#magic_typecast_properties ⇒ Object
-
#magic_typecast_properties_keys ⇒ Object
-
#property?(key) ⇒ Boolean
-
#register(property) ⇒ Object
#property on an Node or Relationship class.
-
#registered_properties ⇒ Object
-
#serialize(name, coder = JSON) ⇒ Object
-
#serialized_properties ⇒ Object
-
#serialized_properties=(serialize_hash) ⇒ Object
-
#serialized_properties_keys ⇒ Object
-
#string_key(k) ⇒ Object
but when this happens many times while loading many objects, it results in a surprisingly significant slowdown.
-
#unregister(name) ⇒ Object
-
#value_for_db(key, value) ⇒ Object
-
#value_for_ruby(key, value) ⇒ Object
-
#value_for_where(key, value) ⇒ Object
#convert_properties_to, #convert_property, converter_for, formatted_for_db?, included, register_converter, #supports_array?, to_other, #typecast_attribute, typecast_attribute, #typecaster_for, typecaster_for
Constructor Details
Each class that includes ActiveGraph::Node or ActiveGraph::Relationship gets one instance of this class.
16
17
18
|
# File 'lib/active_graph/shared/declared_properties.rb', line 16
def initialize(klass)
@klass = klass
end
|
Instance Attribute Details
#klass ⇒ Object
Returns the value of attribute klass.
11
12
13
|
# File 'lib/active_graph/shared/declared_properties.rb', line 11
def klass
@klass
end
|
Instance Method Details
#[](key) ⇒ Object
20
21
22
|
# File 'lib/active_graph/shared/declared_properties.rb', line 20
def [](key)
registered_properties[key.to_sym]
end
|
#attributes_nil_hash ⇒ Object
During object wrap, a hash is needed that contains each declared property with a nil value. The active_attr dependency is capable of providing this but it is expensive and calculated on the fly each time it is called. Rather than rely on that, we build this progressively as properties are registered. When the node or rel is loaded, this is used as a template.
69
70
71
72
73
74
75
76
|
# File 'lib/active_graph/shared/declared_properties.rb', line 69
def attributes_nil_hash
@_attributes_nil_hash ||= {}.tap do |attr_hash|
registered_properties.each_pair do |k, prop_obj|
val = prop_obj.default_value
attr_hash[k.to_s] = val
end
end.freeze
end
|
#attributes_string_map ⇒ Object
During object wrapping, a props hash is built with string keys but ActiveGraph::Core provides symbols. Rather than a `to_s` or `symbolize_keys` during every load, we build a map of symbol-to-string to speed up the process. This increases memory used by the gem but reduces object allocation and GC, so it is faster in practice.
82
83
84
85
86
|
# File 'lib/active_graph/shared/declared_properties.rb', line 82
def attributes_string_map
@_attributes_string_map ||= {}.tap do |attr_hash|
attributes_nil_hash.each_key { |k| attr_hash[k.to_sym] = k }
end.freeze
end
|
#constraint_or_fail!(key, id_property_name, type = :unique) ⇒ Object
45
46
47
48
49
|
# File 'lib/active_graph/shared/declared_properties.rb', line 45
def constraint_or_fail!(key, id_property_name, type = :unique)
return if key == id_property_name
fail "Cannot constraint undeclared property #{property}" unless property?(key)
registered_properties[key].constraint!(type)
end
|
#declared_property_defaults ⇒ Object
The :default option in ActiveGraph::Node#property class method allows for setting a default value instead of nil on declared properties. This holds those values.
53
54
55
|
# File 'lib/active_graph/shared/declared_properties.rb', line 53
def declared_property_defaults
@_default_property_values ||= {}
end
|
#index_or_fail!(key, id_property_name, type = :exact) ⇒ Object
39
40
41
42
43
|
# File 'lib/active_graph/shared/declared_properties.rb', line 39
def index_or_fail!(key, id_property_name, type = :exact)
return if key == id_property_name
fail "Cannot index undeclared property #{key}" unless property?(key)
registered_properties[key].index!(type)
end
|
#indexed_properties ⇒ Object
61
62
63
|
# File 'lib/active_graph/shared/declared_properties.rb', line 61
def indexed_properties
registered_properties.select { |_, p| p.index_or_constraint? }
end
|
#inject_defaults!(object, props) ⇒ Object
157
158
159
160
161
162
|
# File 'lib/active_graph/shared/declared_properties.rb', line 157
def inject_defaults!(object, props)
declared_property_defaults.each_pair do |k, v|
props[k.to_sym] = v.respond_to?(:call) ? v.call : v if object.send(k).nil? && props[k.to_sym].nil?
end
props
end
|
#magic_typecast_properties ⇒ Object
131
132
133
|
# File 'lib/active_graph/shared/declared_properties.rb', line 131
def magic_typecast_properties
@magic_typecast_properties ||= {}
end
|
#magic_typecast_properties_keys ⇒ Object
127
128
129
|
# File 'lib/active_graph/shared/declared_properties.rb', line 127
def magic_typecast_properties_keys
@magic_typecast_properties_keys ||= magic_typecast_properties.keys
end
|
#property?(key) ⇒ Boolean
24
25
26
|
# File 'lib/active_graph/shared/declared_properties.rb', line 24
def property?(key)
registered_properties.key?(key.to_sym)
end
|
#register(property) ⇒ Object
#property on an Node or Relationship class. The DeclaredProperty has specifics about the property, but registration makes the management object aware of it. This is necessary for type conversion, defaults, and inclusion in the nil and string hashes.
31
32
33
34
35
36
37
|
# File 'lib/active_graph/shared/declared_properties.rb', line 31
def register(property)
@_attributes_nil_hash = nil
@_attributes_string_map = nil
registered_properties[property.name] = property
register_magic_typecaster(property) if property.magic_typecaster
declared_property_defaults[property.name] = property.default_value if !property.default_value.nil?
end
|
#registered_properties ⇒ Object
57
58
59
|
# File 'lib/active_graph/shared/declared_properties.rb', line 57
def registered_properties
@_registered_properties ||= {}
end
|
#serialize(name, coder = JSON) ⇒ Object
109
110
111
112
|
# File 'lib/active_graph/shared/declared_properties.rb', line 109
def serialize(name, coder = JSON)
@serialize ||= {}
@serialize[name] = coder
end
|
#serialized_properties ⇒ Object
119
120
121
|
# File 'lib/active_graph/shared/declared_properties.rb', line 119
def serialized_properties
@serialize ||= {}
end
|
#serialized_properties=(serialize_hash) ⇒ Object
114
115
116
117
|
# File 'lib/active_graph/shared/declared_properties.rb', line 114
def serialized_properties=(serialize_hash)
@serialized_property_keys = nil
@serialize = serialize_hash.clone
end
|
#serialized_properties_keys ⇒ Object
123
124
125
|
# File 'lib/active_graph/shared/declared_properties.rb', line 123
def serialized_properties_keys
@serialized_property_keys ||= serialized_properties.keys
end
|
#string_key(k) ⇒ Object
but when this happens many times while loading many objects, it results in a surprisingly significant slowdown. The branching logic handles what happens if a property can't be found. The first option attempts to find it in the existing hash. 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 future lookups. The third calls `to_s`. This would happen if undeclared properties are found on the object. We could add them to the string map but that would result in unchecked, un-GCed memory consumption. In the event that someone is adding properties dynamically, maybe through user input, this would be bad.
97
98
99
|
# File 'lib/active_graph/shared/declared_properties.rb', line 97
def string_key(k)
attributes_string_map[k] || string_map_id_property(k) || k.to_s
end
|
#unregister(name) ⇒ Object
101
102
103
104
105
106
107
|
# File 'lib/active_graph/shared/declared_properties.rb', line 101
def unregister(name)
fail ArgumentError, "Argument `#{name}` not an attribute" if not registered_properties[name]
registered_properties.delete(name)
unregister_magic_typecaster(name)
unregister_property_default(name)
end
|
#value_for_db(key, value) ⇒ Object
147
148
149
150
|
# File 'lib/active_graph/shared/declared_properties.rb', line 147
def value_for_db(key, value)
return value unless registered_properties[key]
convert_property(key, value, :to_db)
end
|
#value_for_ruby(key, value) ⇒ Object
152
153
154
155
|
# File 'lib/active_graph/shared/declared_properties.rb', line 152
def value_for_ruby(key, value)
return unless registered_properties[key]
convert_property(key, value, :to_ruby)
end
|
#value_for_where(key, value) ⇒ Object
136
137
138
139
140
141
142
143
144
145
|
# File 'lib/active_graph/shared/declared_properties.rb', line 136
def value_for_where(key, value)
return value unless prop = registered_properties[key]
return value_for_db(key, value) if prop.typecaster && prop.typecaster.convert_type == value.class
if should_convert_for_where?(key, value)
value_for_db(key, value)
else
value
end
end
|