Class: Explicit::Type::OneOf
- Inherits:
-
Explicit::Type
- Object
- Explicit::Type
- Explicit::Type::OneOf
- Defined in:
- lib/explicit/type/one_of.rb
Instance Attribute Summary collapse
-
#subtypes ⇒ Object
readonly
Returns the value of attribute subtypes.
Attributes inherited from Explicit::Type
#auth_type, #default, #description, #nilable, #param_location
Instance Method Summary collapse
- #guess_error_for_intended_subtype_via_matching_keys(value:, errors:) ⇒ Object
- #guess_error_for_intended_subtype_via_matching_literal(value:, errors:) ⇒ Object
-
#initialize(subtypes:) ⇒ OneOf
constructor
A new instance of OneOf.
- #json_schema(flavour) ⇒ Object
- #validate(value) ⇒ Object
Methods inherited from Explicit::Type
#auth_basic?, #auth_bearer?, build, #error_i18n, #mcp_schema, #merge_base_json_schema, #param_location_body?, #param_location_path?, #param_location_query?, #required?, #swagger_i18n, #swagger_schema
Constructor Details
#initialize(subtypes:) ⇒ OneOf
Returns a new instance of OneOf.
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
# File 'lib/explicit/type/one_of.rb', line 6 def initialize(subtypes:) @subtypes = subtypes.map { Explicit::Type.build(_1) } @subtypes_are_records = @subtypes.all? { _1.is_a?(Explicit::Type::Record) } @literal_attribute_name_shared_by_all_subtypes = nil if @subtypes_are_records literal_types = @subtypes.map do |subtype| subtype.attributes.find { |name, type| type.is_a?(Explicit::Type::Literal) } end literal_names = literal_types.map { |name, _| name }.uniq if literal_types.all?(&:present?) && literal_names.one? @literal_attribute_name_shared_by_all_subtypes = literal_names.first end end end |
Instance Attribute Details
#subtypes ⇒ Object (readonly)
Returns the value of attribute subtypes.
4 5 6 |
# File 'lib/explicit/type/one_of.rb', line 4 def subtypes @subtypes end |
Instance Method Details
#guess_error_for_intended_subtype_via_matching_keys(value:, errors:) ⇒ Object
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/explicit/type/one_of.rb', line 70 def guess_error_for_intended_subtype_via_matching_keys(value:, errors:) return nil if !@subtypes_are_records return nil if !value.is_a?(::Hash) matches = @subtypes.zip(errors).filter_map do |(subtype, error)| s1 = Set.new(subtype.attributes.keys) s2 = Set.new(value.keys) if s1.intersection(s2).size.positive? { subtype:, error: } else nil end end return matches.first[:error] if matches.one? nil end |
#guess_error_for_intended_subtype_via_matching_literal(value:, errors:) ⇒ Object
61 62 63 64 65 66 67 68 |
# File 'lib/explicit/type/one_of.rb', line 61 def guess_error_for_intended_subtype_via_matching_literal(value:, errors:) return nil if !@literal_attribute_name_shared_by_all_subtypes return nil if !value.is_a?(::Hash) errors.find do |error| !error.key?(@literal_attribute_name_shared_by_all_subtypes) end end |
#json_schema(flavour) ⇒ Object
104 105 106 107 108 |
# File 'lib/explicit/type/one_of.rb', line 104 def json_schema(flavour) raise ::NotImplementedError if flavour == :mcp { oneOf: subtypes.map(&:swagger_schema) } end |
#validate(value) ⇒ Object
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 |
# File 'lib/explicit/type/one_of.rb', line 24 def validate(value) errors = [] @subtypes.each do |subtype| case subtype.validate(value) in [:ok, validated_value] return [ :ok, validated_value ] in [:error, err] errors << err end end if (err = guess_error_for_intended_subtype_via_matching_literal(value:, errors:)) return [ :error, err ] end if (err = guess_error_for_intended_subtype_via_matching_keys(value:, errors:)) return [ :error, err ] end separator = if ::I18n.exists?("explicit.errors.one_of_separator") ::I18n.t("explicit.errors.one_of_separator") else ::I18n.t("explicit.errors.one_of_separator", locale: :en) end error = if @subtypes_are_records errors.map { ::JSON.pretty_generate(_1) }.join("\n\n#{separator}\n\n") else errors.join(" #{separator} ") end [ :error, error ] end |