class RSchema::Schemas::FixedHash
A schema that matches `Hash` objects with known keys
@example A typical fixed hash schema
schema = RSchema.define do fixed_hash( name: _String, optional(:age) => _Integer, ) end schema.valid?({ name: "Tom" }) #=> true schema.valid?({ name: "Dane", age: 55 }) #=> true
Constants
- Attribute
Attributes
attributes[R]
Public Class Methods
new(attributes)
click to toggle source
# File lib/rschema/schemas/fixed_hash.rb, line 21 def initialize(attributes) @attributes = attributes end
Public Instance Methods
[](attr_key)
click to toggle source
# File lib/rschema/schemas/fixed_hash.rb, line 46 def [](attr_key) attributes.find { |attr| attr.key == attr_key } end
call(value, options)
click to toggle source
# File lib/rschema/schemas/fixed_hash.rb, line 25 def call(value, options) return not_a_hash_result(value) unless value.is_a?(Hash) return missing_attrs_result(value) if missing_keys(value).any? return extraneous_attrs_result(value) if extraneous_keys(value).any? subresults = attr_subresults(value, options) if subresults.values.any?(&:invalid?) Result.failure(failure_error(subresults)) else Result.success(success_value(subresults)) end end
merge(new_attributes)
click to toggle source
Creates a new {FixedHash} schema with the given attributes merged in
@param new_attributes [Array<Attribute>] The attributes to merge @return [FixedHash] A new schema with the given attributes merged in
@example Merging new attributes into an existing {Schemas::FixedHash}
person_schema = RSchema.define_hash {{ name: _String, age: _Integer, }} person_schema.valid?(name: "t", age: 5) #=> true person_schema.valid?(name: "t", age: 5, id: 3) #=> false person_with_id_schema = RSchema.define do person_schema.merge(attributes( id: _Integer, )) end person_with_id_schema.valid?(name: "t", age: 5, id: 3) #=> true person_with_id_schema.valid?(name: "t", age: 5) #=> false
# File lib/rschema/schemas/fixed_hash.rb, line 72 def merge(new_attributes) merged_attrs = (attributes + new_attributes) .map { |attr| [attr.key, attr] } .to_h .values self.class.new(merged_attrs) end
with_wrapped_subschemas(wrapper)
click to toggle source
# File lib/rschema/schemas/fixed_hash.rb, line 38 def with_wrapped_subschemas(wrapper) wrapped_attributes = attributes.map do |attr| attr.with_wrapped_value_schema(wrapper) end self.class.new(wrapped_attributes) end
without(attribute_keys)
click to toggle source
Creates a new {FixedHash} schema with the given attributes removed
@param attribute_keys [Array<Object>] The keys to remove @return [FixedHash] A new schema with the given attributes removed
@example Removing an attribute
cat_and_dog = RSchema.define_hash {{ dog: _String, cat: _String, }} only_cat = RSchema.define { cat_and_dog.without(:dog) } only_cat.valid?({ cat: 'meow' }) #=> true only_cat.valid?({ cat: 'meow', dog: 'woof' }) #=> false
# File lib/rschema/schemas/fixed_hash.rb, line 97 def without(attribute_keys) filtered_attrs = attributes .reject { |attr| attribute_keys.include?(attr.key) } self.class.new(filtered_attrs) end
Private Instance Methods
attr_subresults(value, options)
click to toggle source
# File lib/rschema/schemas/fixed_hash.rb, line 150 def attr_subresults(value, options) subresults_by_key = {} @attributes.map do |attr| next unless value.key?(attr.key) subresult = attr.value_schema.call(value[attr.key], options) subresults_by_key[attr.key] = subresult break if subresult.invalid? && options.fail_fast? end subresults_by_key end
extraneous_attrs_result(value)
click to toggle source
# File lib/rschema/schemas/fixed_hash.rb, line 137 def extraneous_attrs_result(value) Result.failure( Error.new( schema: self, value: value, symbolic_name: :extraneous_attributes, vars: { extraneous_keys: extraneous_keys(value) }, ), ) end
extraneous_keys(value)
click to toggle source
# File lib/rschema/schemas/fixed_hash.rb, line 132 def extraneous_keys(value) allowed_keys = attributes.map(&:key) value.keys.reject { |k| allowed_keys.include?(k) } end
failure_error(subresults)
click to toggle source
# File lib/rschema/schemas/fixed_hash.rb, line 163 def failure_error(subresults) subresults .select { |_, result| result.invalid? } .map { |key, result| [key, result.error] } .to_h end
missing_attrs_result(value)
click to toggle source
# File lib/rschema/schemas/fixed_hash.rb, line 119 def missing_attrs_result(value) Result.failure( Error.new( schema: self, value: value, symbolic_name: :missing_attributes, vars: { missing_keys: missing_keys(value) }, ), ) end
missing_keys(value)
click to toggle source
# File lib/rschema/schemas/fixed_hash.rb, line 112 def missing_keys(value) attributes .reject(&:optional) .map(&:key) .reject { |k| value.key?(k) } end
not_a_hash_result(value)
click to toggle source
# File lib/rschema/schemas/fixed_hash.rb, line 176 def not_a_hash_result(value) Result.failure( Error.new( schema: self, value: value, symbolic_name: :not_a_hash, ), ) end
success_value(subresults)
click to toggle source
# File lib/rschema/schemas/fixed_hash.rb, line 170 def success_value(subresults) subresults .map { |key, attr_result| [key, attr_result.value] } .to_h end