Class: TSJSON::DiscriminatorMap
- Inherits:
-
Object
- Object
- TSJSON::DiscriminatorMap
- Defined in:
- lib/types/discriminator_map.rb
Instance Attribute Summary collapse
-
#discriminators ⇒ Object
readonly
Returns the value of attribute discriminators.
Instance Method Summary collapse
- #[](value) ⇒ Object
-
#initialize(types) ⇒ DiscriminatorMap
constructor
A new instance of DiscriminatorMap.
- #validate(object) ⇒ Object
Constructor Details
#initialize(types) ⇒ DiscriminatorMap
Returns a new instance of DiscriminatorMap.
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/types/discriminator_map.rb', line 7 def initialize(types) # Hash with discriminators. # Key - name of the field # Value - enum with all possible field values discriminators = {} # Hash of form H[field_name][field_value]=[...all types that matches field_name=field_value] hash = {} types.each do |t| # for each field inside each type t.fields.each do |f| next unless f[:type].is_a?(Literal) || f[:type].is_a?(LiteralUnion) # only literal types may be used as discriminators field_name = f[:name] field_types = f[:type].is_a?(Literal) ? [f[:type]] : f[:type].types # iterate over all types of LiteralUnion field_types.each do |field_type| # create discriminator enums if discriminators[field_name] == nil discriminators[field_name] = LiteralUnion.new([field_type]) else discriminators[field_name] = discriminators[field_name].push_type(field_type) end # create array of types for each discriminator if hash[field_name] == nil hash[field_name] = { field_type.value => [t] } else if hash[field_name][field_type.value] == nil hash[field_name][field_type.value] = [t] else hash[field_name][field_type.value].push(t) end end end end end # delete discriminators that appear in all types or in one only hash.each do |field_name, values_hash| if values_hash.values.length == 1 && values_hash.values[0].length == types.length discriminators.delete(field_name) end end # filter valid discriminators hash = hash.reject do |field_name, values_hash| values_hash.values.length == 1 && values_hash.values[0].length == types.length end.to_h # check that all types are mapped mapped_types = hash.values.map(&:values).flatten.uniq if (mapped_types.length < types.length) raise NotEnoughDiscriminators.new(types: types) end # replace array of types with single type or nested map @hash = hash.transform_values do |values_hash| values_hash.transform_values do |types| types.length == 1 ? types.first : DiscriminatorMap.new(types) end end # create discriminators array sorted by appearance count @discriminators = discriminators.map { |k, v| { field: k, value: v } }.sort do |a, b| b[:value].size <=> a[:value].size end end |
Instance Attribute Details
#discriminators ⇒ Object (readonly)
Returns the value of attribute discriminators.
5 6 7 |
# File 'lib/types/discriminator_map.rb', line 5 def discriminators @discriminators end |
Instance Method Details
#[](value) ⇒ Object
112 113 114 |
# File 'lib/types/discriminator_map.rb', line 112 def [](value) @hash[value] end |
#validate(object) ⇒ Object
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/types/discriminator_map.rb', line 83 def validate(object) object = object&.transform_keys!(&:to_s) discriminators.each do |discriminator| field = discriminator[:field] expected_value = discriminator[:value] value = object[field] unless value.nil? unless expected_value.has?(value) raise UnexpectedValueError.new( field: field, expected_values: expected_value.to_json, received: value ) end return @hash[field][value].validate(object) end end raise CantDistinguishTypeError.new( discriminators: discriminators.map { |d| { field: d[:field], values: d[:value].to_json } } ) end |