module T::Props::Serializable
typed: false
Public Instance Methods
deserialize(hash, strict=false)
click to toggle source
Populates the property values on this object with the values from a hash. In general, prefer to use {.from_hash} to construct a new instance, instead of loading into an existing instance.
@param hash [Hash<String, Object>] The hash to take property
values from.
@param strict [T::Boolean] (false) If true, raise an exception if
the hash contains keys that do not correspond to any known props on this instance.
@return [void]
# File lib/types/props/serializable.rb, line 59 def deserialize(hash, strict=false) begin hash_keys_matching_props = __t_props_generated_deserialize(hash) rescue => e msg = self.class.decorator.message_with_generated_source_context( e, :__t_props_generated_deserialize, :generate_deserialize_source ) if msg begin raise e.class.new(msg) rescue ArgumentError raise TypeError.new(msg) end else raise end end if hash.size > hash_keys_matching_props serialized_forms = self.class.decorator.prop_by_serialized_forms extra = hash.reject {|k, _| serialized_forms.key?(k)} # `extra` could still be empty here if the input matches a `dont_store` prop; # historically, we just ignore those if !extra.empty? if strict raise "Unknown properties for #{self.class.name}: #{extra.keys.inspect}" else @_extra_props = extra end end end end
serialize(strict=true)
click to toggle source
Serializes this object to a hash, suitable for conversion to JSON/BSON.
@param strict [T::Boolean] (true) If false, do not raise an
exception if this object has mandatory props with missing values.
@return [Hash] A serialization of this object.
# File lib/types/props/serializable.rb, line 18 def serialize(strict=true) begin h = __t_props_generated_serialize(strict) rescue => e msg = self.class.decorator.message_with_generated_source_context( e, :__t_props_generated_serialize, :generate_serialize_source ) if msg begin raise e.class.new(msg) rescue ArgumentError raise TypeError.new(msg) end else raise end end h.merge!(@_extra_props) if @_extra_props h end
with(changed_props)
click to toggle source
with() will clone the old object to the new object and merge the specified props to the new object.
# File lib/types/props/serializable.rb, line 103 def with(changed_props) with_existing_hash(changed_props, existing_hash: self.serialize) end
Private Instance Methods
__t_props_generated_deserialize(hash)
click to toggle source
# File lib/types/props/serializable.rb, line 95 def __t_props_generated_deserialize(hash) # No-op; will be overridden if there are any props. # # To see the definition for class `Foo`, run `Foo.decorator.send(:generate_deserialize_source)` 0 end
__t_props_generated_serialize(strict)
click to toggle source
# File lib/types/props/serializable.rb, line 42 def __t_props_generated_serialize(strict) # No-op; will be overridden if there are any props. # # To see the definition for class `Foo`, run `Foo.decorator.send(:generate_serialize_source)` {} end
raise_deserialization_error(prop_name, value, orig_error)
click to toggle source
# File lib/types/props/serializable.rb, line 160 def raise_deserialization_error(prop_name, value, orig_error) T::Configuration.soft_assert_handler( 'Deserialization error (probably unexpected stored type)', storytime: { klass: self.class, prop: prop_name, value: value, error: orig_error.message, notify: 'djudd' } ) end
recursive_stringify_keys(obj)
click to toggle source
# File lib/types/props/serializable.rb, line 107 def recursive_stringify_keys(obj) if obj.is_a?(Hash) new_obj = obj.class.new obj.each do |k, v| new_obj[k.to_s] = recursive_stringify_keys(v) end elsif obj.is_a?(Array) new_obj = obj.map {|v| recursive_stringify_keys(v)} else new_obj = obj end new_obj end
required_prop_missing_from_deserialize(prop)
click to toggle source
Marks this property as missing during deserialize
# File lib/types/props/serializable.rb, line 154 def required_prop_missing_from_deserialize(prop) @_required_props_missing_from_deserialize ||= Set[] @_required_props_missing_from_deserialize << prop nil end
required_prop_missing_from_serialize(prop)
click to toggle source
Asserts if this property is missing during strict serialize
# File lib/types/props/serializable.rb, line 139 def required_prop_missing_from_serialize(prop) if @_required_props_missing_from_deserialize&.include?(prop) # If the prop was already missing during deserialization, that means the application # code already had to deal with a nil value, which means we wouldn't be accomplishing # much by raising here (other than causing an unnecessary breakage). T::Configuration.log_info_handler( "chalk-odm: missing required property in serialize", prop: prop, class: self.class.name, id: self.class.decorator.get_id(self) ) else raise TypeError.new("#{self.class.name}.#{prop} not set for non-optional prop") end end
with_existing_hash(changed_props, existing_hash:)
click to toggle source
# File lib/types/props/serializable.rb, line 121 def with_existing_hash(changed_props, existing_hash:) serialized = existing_hash new_val = self.class.from_hash(serialized.merge(recursive_stringify_keys(changed_props))) old_extra = self.instance_variable_get(:@_extra_props) new_extra = new_val.instance_variable_get(:@_extra_props) if old_extra != new_extra difference = if old_extra new_extra.reject {|k, v| old_extra[k] == v} else new_extra end raise ArgumentError.new("Unexpected arguments: input(#{changed_props}), unexpected(#{difference})") end new_val end