Class: MediaTypes::Scheme
- Inherits:
-
Object
- Object
- MediaTypes::Scheme
- Defined in:
- lib/media_types/scheme.rb,
lib/media_types/scheme/links.rb,
lib/media_types/scheme/rules.rb,
lib/media_types/scheme/any_of.rb,
lib/media_types/scheme/errors.rb,
lib/media_types/scheme/allow_nil.rb,
lib/media_types/scheme/attribute.rb,
lib/media_types/scheme/not_strict.rb,
lib/media_types/scheme/output_type_guard.rb,
lib/media_types/scheme/missing_validation.rb,
lib/media_types/scheme/output_empty_guard.rb,
lib/media_types/scheme/validation_options.rb,
lib/media_types/scheme/enumeration_context.rb,
lib/media_types/scheme/enumeration_of_type.rb,
lib/media_types/scheme/rules_exhausted_guard.rb,
lib/media_types/scheme/output_iterator_with_predicate.rb
Overview
Media Type Schemes can validate content to a media type, by itself. Used by the ‘validations` dsl.
Defined Under Namespace
Classes: AnyOverwritingNotStrictError, Attribute, CaseEqualityWithList, ConflictingTypeDefinitionError, DuplicateAnyRuleError, DuplicateKeyError, DuplicateNotStrictRuleError, DuplicateStringKeyError, DuplicateSymbolKeyError, EmptyOutputError, EnumerationContext, EnumerationOfType, ExhaustedOutputError, KeyTypeError, Links, MissingValidation, NotStrict, NotStrictOverwritingAnyError, OutputEmptyGuard, OutputIteratorWithPredicate, OutputTypeGuard, OutputTypeMismatch, OverwritingRuleError, Rules, RulesExhaustedGuard, StrictValidationError, StringOverwritingSymbolError, SymbolOverwritingStringError, ValidationError, ValidationOptions
Instance Attribute Summary collapse
-
#asserted_sane ⇒ Object
(also: #asserted_sane?)
readonly
Returns the value of attribute asserted_sane.
-
#fixtures ⇒ Object
Returns the value of attribute fixtures.
-
#rules ⇒ Object
readonly
Returns the value of attribute rules.
-
#type_attributes ⇒ Object
Returns the value of attribute type_attributes.
Class Method Summary collapse
-
.AllowNil(klazz) ⇒ CaseEqualityWithList
noinspection RubyClassMethodNamingConvention.
-
.AnyOf(*klazzes) ⇒ CaseEqualityWithList
noinspection RubyClassMethodNamingConvention.
Instance Method Summary collapse
-
#AllowNil(klazz) ⇒ CaseEqualityWithList
noinspection RubyInstanceMethodNamingConvention.
-
#any(scheme = nil, expected_type: ::Hash, allow_empty: false, &block) ⇒ Object
Allow for any key.
-
#AnyOf(*klazzes) ⇒ CaseEqualityWithList
noinspection RubyInstanceMethodNamingConvention.
- #assert_fail(fixture) ⇒ Object
- #assert_pass(fixture) ⇒ Object
-
#attribute(key, type = nil, optional: false, **opts, &block) ⇒ Object
Adds an attribute to the schema If a
block
is given, uses that to test against instead oftype
. -
#collection(key, scheme = nil, allow_empty: false, expected_type: ::Array, optional: false, &block) ⇒ Object
Expect a collection such as an array or hash.
-
#empty ⇒ Object
Mark object as a valid empty object.
-
#initialize(allow_empty: false, expected_type: ::Object, &block) ⇒ Scheme
constructor
Creates a new scheme.
- #inspect(indentation = 0) ⇒ Object
-
#link(*args, **opts, &block) ⇒ Object
Expect a link.
-
#merge(scheme, &block) ⇒ Object
Merges a
scheme
into this scheme without changing the incomingscheme
. -
#not_strict ⇒ Object
Allow for extra keys in the schema/collection even when passing strict: true to #validate!.
-
#remove_current_dir_from_stack(stack) ⇒ Object
Removes all calls originating in current dir from given stack We need this so that we find out the caller of an assert_pass/fail in the caller_locations Which gets polluted by Scheme consecutively executing blocks within the validation blocks.
- #run_fixture_validations(expect_symbol_keys, backtrace = []) ⇒ Object
-
#valid?(output, **opts) ⇒ TrueClass, FalseClass
Checks if the
output
is valid. -
#validate(output, options = nil, **opts) ⇒ TrueClass
Validates the
output
and raises on certain validation errors. - #validate!(output, call_options, **_opts) ⇒ Object
- #validate_default_scheme_fixtures(expect_symbol_keys, backtrace) ⇒ Object
- #validate_fixture(fixture_data, expect_symbol_keys, backtrace = []) ⇒ Object
- #validate_nested_scheme_fixtures(expect_symbol_keys, backtrace) ⇒ Object
- #validate_scheme_fixtures(expect_symbol_keys, backtrace) ⇒ Object
Constructor Details
#initialize(allow_empty: false, expected_type: ::Object, &block) ⇒ Scheme
Creates a new scheme
96 97 98 99 100 101 102 103 |
# File 'lib/media_types/scheme.rb', line 96 def initialize(allow_empty: false, expected_type: ::Object, &block) self.rules = Rules.new(allow_empty: allow_empty, expected_type: expected_type) self.type_attributes = {} self.fixtures = [] self.asserted_sane = false instance_exec(&block) if block_given? end |
Instance Attribute Details
#asserted_sane ⇒ Object Also known as: asserted_sane?
Returns the value of attribute asserted_sane.
106 107 108 |
# File 'lib/media_types/scheme.rb', line 106 def asserted_sane @asserted_sane end |
#fixtures ⇒ Object
Returns the value of attribute fixtures.
105 106 107 |
# File 'lib/media_types/scheme.rb', line 105 def fixtures @fixtures end |
#rules ⇒ Object
Returns the value of attribute rules.
106 107 108 |
# File 'lib/media_types/scheme.rb', line 106 def rules @rules end |
#type_attributes ⇒ Object
Returns the value of attribute type_attributes.
105 106 107 |
# File 'lib/media_types/scheme.rb', line 105 def type_attributes @type_attributes end |
Class Method Details
.AllowNil(klazz) ⇒ CaseEqualityWithList
noinspection RubyClassMethodNamingConvention
Allows the wrapped klazz
to be nil
15 16 17 |
# File 'lib/media_types/scheme/allow_nil.rb', line 15 def AllowNil(klazz) # rubocop:disable Naming/MethodName AnyOf(NilClass, klazz) end |
.AnyOf(*klazzes) ⇒ CaseEqualityWithList
noinspection RubyClassMethodNamingConvention
Allows it
to be any of the wrapped klazzes
26 27 28 |
# File 'lib/media_types/scheme/any_of.rb', line 26 def AnyOf(*klazzes) # rubocop:disable Naming/MethodName CaseEqualityWithList.new(klazzes) end |
Instance Method Details
#AllowNil(klazz) ⇒ CaseEqualityWithList
noinspection RubyInstanceMethodNamingConvention
Allows the wrapped klazz
to be nil
26 27 28 |
# File 'lib/media_types/scheme/allow_nil.rb', line 26 def AllowNil(klazz) # rubocop:disable Naming/MethodName self.class.AllowNil(klazz) end |
#any(scheme = nil, expected_type: ::Hash, allow_empty: false, &block) ⇒ Object
Allow for any key.
The +&block+ defines the Schema for each value.
261 262 263 264 265 266 267 268 269 270 271 272 273 |
# File 'lib/media_types/scheme.rb', line 261 def any(scheme = nil, expected_type: ::Hash, allow_empty: false, &block) raise ConflictingTypeDefinitionError, 'You cannot apply a block to a non-hash typed property, either remove the type or the block' if scheme != ::Hash && block_given? && !scheme.nil? unless block_given? if scheme.is_a?(Scheme) return rules.default = scheme end return rules.default = Attribute.new(scheme) end rules.default = Scheme.new(allow_empty: allow_empty, expected_type: expected_type, &block) end |
#AnyOf(*klazzes) ⇒ CaseEqualityWithList
noinspection RubyInstanceMethodNamingConvention
Allows it
to be any of the wrapped klazzes
37 38 39 |
# File 'lib/media_types/scheme/any_of.rb', line 37 def AnyOf(*klazzes) # rubocop:disable Naming/MethodName self.class.AnyOf(*klazzes) end |
#assert_fail(fixture) ⇒ Object
439 440 441 442 |
# File 'lib/media_types/scheme.rb', line 439 def assert_fail(fixture) reduced_stack = remove_current_dir_from_stack(caller_locations) @fixtures << FixtureData.new(caller: reduced_stack.first, fixture: fixture, expect_to_pass: false) end |
#assert_pass(fixture) ⇒ Object
434 435 436 437 |
# File 'lib/media_types/scheme.rb', line 434 def assert_pass(fixture) reduced_stack = remove_current_dir_from_stack(caller_locations) @fixtures << FixtureData.new(caller: reduced_stack.first, fixture: fixture, expect_to_pass: true) end |
#attribute(key, type = nil, optional: false, **opts, &block) ⇒ Object
Adds an attribute to the schema
If a +block+ is given, uses that to test against instead of +type+
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 |
# File 'lib/media_types/scheme.rb', line 205 def attribute(key, type = nil, optional: false, **opts, &block) raise ConflictingTypeDefinitionError, 'You cannot apply a block to a non-hash typed attribute, either remove the type or the block' if type != ::Hash && block_given? && !type.nil? type ||= ::Object if block_given? return collection(key, expected_type: ::Hash, optional: optional, **opts, &block) end if type.is_a?(Scheme) return rules.add(key, type, optional: optional) end rules.add(key, Attribute.new(type, **opts, &block), optional: optional) end |
#collection(key, scheme = nil, allow_empty: false, expected_type: ::Array, optional: false, &block) ⇒ Object
Expect a collection such as an array or hash.
The +block+ defines the Schema for each item in that collection.
350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 |
# File 'lib/media_types/scheme.rb', line 350 def collection(key, scheme = nil, allow_empty: false, expected_type: ::Array, optional: false, &block) raise ConflictingTypeDefinitionError, 'You cannot apply a block to a non-hash typed collection, either remove the type or the block' if scheme != ::Hash && block_given? && !scheme.nil? unless block_given? return rules.add( key, EnumerationOfType.new( scheme, enumeration_type: expected_type, allow_empty: allow_empty ), optional: optional ) end rules.add(key, Scheme.new(allow_empty: allow_empty, expected_type: expected_type, &block), optional: optional) end |
#empty ⇒ Object
Mark object as a valid empty object
422 423 |
# File 'lib/media_types/scheme.rb', line 422 def empty end |
#inspect(indentation = 0) ⇒ Object
425 426 427 428 429 430 431 432 |
# File 'lib/media_types/scheme.rb', line 425 def inspect(indentation = 0) tabs = ' ' * indentation [ "#{tabs}[Scheme]", rules.inspect(indentation + 1), "#{tabs}[/Scheme]" ].join("\n") end |
#link(*args, **opts, &block) ⇒ Object
Expect a link
402 403 404 405 406 407 408 |
# File 'lib/media_types/scheme.rb', line 402 def link(*args, **opts, &block) rules.fetch(:_links) do Links.new.tap do |links| rules.add(:_links, links) end end.link(*args, **opts, &block) end |
#merge(scheme, &block) ⇒ Object
Merges a scheme
into this scheme without changing the incoming scheme
280 281 282 283 |
# File 'lib/media_types/scheme.rb', line 280 def merge(scheme, &block) self.rules = rules.merge(scheme.send(:rules)) instance_exec(&block) if block_given? end |
#not_strict ⇒ Object
Allow for extra keys in the schema/collection even when passing strict: true to #validate!
306 307 308 |
# File 'lib/media_types/scheme.rb', line 306 def not_strict rules.default = NotStrict.new end |
#remove_current_dir_from_stack(stack) ⇒ Object
Removes all calls originating in current dir from given stack We need this so that we find out the caller of an assert_pass/fail in the caller_locations Which gets polluted by Scheme consecutively executing blocks within the validation blocks
447 448 449 |
# File 'lib/media_types/scheme.rb', line 447 def remove_current_dir_from_stack(stack) stack.reject { |location| location.path.include?(__dir__) } end |
#run_fixture_validations(expect_symbol_keys, backtrace = []) ⇒ Object
484 485 486 487 488 489 490 491 492 |
# File 'lib/media_types/scheme.rb', line 484 def run_fixture_validations(expect_symbol_keys, backtrace = []) fixture_errors = validate_scheme_fixtures(expect_symbol_keys, backtrace) fixture_errors += validate_nested_scheme_fixtures(expect_symbol_keys, backtrace) fixture_errors += validate_default_scheme_fixtures(expect_symbol_keys, backtrace) raise AssertionError, fixture_errors unless fixture_errors.empty? self.asserted_sane = true end |
#valid?(output, **opts) ⇒ TrueClass, FalseClass
Checks if the output
is valid
120 121 122 123 124 125 126 |
# File 'lib/media_types/scheme.rb', line 120 def valid?(output, **opts) validate(output, **opts) rescue ExhaustedOutputError !opts.fetch(:exhaustive) { true } rescue ValidationError false end |
#validate(output, options = nil, **opts) ⇒ TrueClass
Validates the output
and raises on certain validation errors
146 147 148 149 150 151 152 153 |
# File 'lib/media_types/scheme.rb', line 146 def validate(output, = nil, **opts) ||= ValidationOptions.new(**opts) .context = output catch(:end) do validate!(output, , context: nil) end end |
#validate!(output, call_options, **_opts) ⇒ Object
158 159 160 161 162 |
# File 'lib/media_types/scheme.rb', line 158 def validate!(output, , **_opts) OutputTypeGuard.call(output, , rules: rules) OutputEmptyGuard.call(output, , rules: rules) RulesExhaustedGuard.call(output, , rules: rules) end |
#validate_default_scheme_fixtures(expect_symbol_keys, backtrace) ⇒ Object
475 476 477 478 479 480 481 482 |
# File 'lib/media_types/scheme.rb', line 475 def validate_default_scheme_fixtures(expect_symbol_keys, backtrace) return [] unless @rules.default.is_a?(Scheme) @rules.default.run_fixture_validations(expect_symbol_keys, backtrace.dup.append('*')) [] rescue AssertionError => e e.fixture_errors end |
#validate_fixture(fixture_data, expect_symbol_keys, backtrace = []) ⇒ Object
494 495 496 497 498 499 500 501 502 503 504 505 506 |
# File 'lib/media_types/scheme.rb', line 494 def validate_fixture(fixture_data, expect_symbol_keys, backtrace = []) json = JSON.parse(fixture_data.fixture, { symbolize_names: expect_symbol_keys }) expected_key_type = expect_symbol_keys ? Symbol : String begin validate(json, expected_key_type: expected_key_type, backtrace: backtrace) unless fixture_data.expect_to_pass? raise UnexpectedValidationResultError.new(fixture_data.caller, 'No error encounterd whilst expecting to') end rescue MediaTypes::Scheme::ValidationError => e raise UnexpectedValidationResultError.new(fixture_data.caller, e) if fixture_data.expect_to_pass? end end |
#validate_nested_scheme_fixtures(expect_symbol_keys, backtrace) ⇒ Object
462 463 464 465 466 467 468 469 470 471 472 473 |
# File 'lib/media_types/scheme.rb', line 462 def validate_nested_scheme_fixtures(expect_symbol_keys, backtrace) @rules.flat_map do |key, rule| next unless rule.is_a?(Scheme) || rule.is_a?(Links) begin rule.run_fixture_validations(expect_symbol_keys, backtrace.dup.append(key)) nil rescue AssertionError => e e.fixture_errors end end.compact end |
#validate_scheme_fixtures(expect_symbol_keys, backtrace) ⇒ Object
451 452 453 454 455 456 457 458 459 460 |
# File 'lib/media_types/scheme.rb', line 451 def validate_scheme_fixtures(expect_symbol_keys, backtrace) @fixtures.map do |fixture_data| begin validate_fixture(fixture_data, expect_symbol_keys, backtrace) nil rescue UnexpectedValidationResultError => e e end end.compact end |