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, loose: false) ⇒ Object
- #assert_pass(fixture, loose: false) ⇒ 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, view: 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.
-
#index(optional: false) ⇒ Object
Expect an index of links.
-
#initialize(allow_empty: false, expected_type: ::Object, current_type: nil, registry: nil, &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, current_type: nil, registry: nil, &block) ⇒ Scheme
Creates a new scheme
97 98 99 100 101 102 103 104 105 106 |
# File 'lib/media_types/scheme.rb', line 97 def initialize(allow_empty: false, expected_type: ::Object, current_type: nil, registry: nil, &block) self.rules = Rules.new(allow_empty: allow_empty, expected_type: expected_type) self.type_attributes = {} self.fixtures = [] self.asserted_sane = false @registry = registry @current_type = current_type 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.
109 110 111 |
# File 'lib/media_types/scheme.rb', line 109 def asserted_sane @asserted_sane end |
#fixtures ⇒ Object
Returns the value of attribute fixtures.
108 109 110 |
# File 'lib/media_types/scheme.rb', line 108 def fixtures @fixtures end |
#rules ⇒ Object
Returns the value of attribute rules.
109 110 111 |
# File 'lib/media_types/scheme.rb', line 109 def rules @rules end |
#type_attributes ⇒ Object
Returns the value of attribute type_attributes.
108 109 110 |
# File 'lib/media_types/scheme.rb', line 108 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.
264 265 266 267 268 269 270 271 272 273 274 275 276 |
# File 'lib/media_types/scheme.rb', line 264 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, registry: @registry, current_type: @current_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, loose: false) ⇒ Object
461 462 463 464 |
# File 'lib/media_types/scheme.rb', line 461 def assert_fail(fixture, loose: false) reduced_stack = remove_current_dir_from_stack(caller_locations) @fixtures << FixtureData.new(caller: reduced_stack.first, fixture: fixture, expect_to_pass: false, loose: loose) end |
#assert_pass(fixture, loose: false) ⇒ Object
456 457 458 459 |
# File 'lib/media_types/scheme.rb', line 456 def assert_pass(fixture, loose: false) reduced_stack = remove_current_dir_from_stack(caller_locations) @fixtures << FixtureData.new(caller: reduced_stack.first, fixture: fixture, expect_to_pass: true, loose: loose) 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+
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 |
# File 'lib/media_types/scheme.rb', line 208 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, view: 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.
353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 |
# File 'lib/media_types/scheme.rb', line 353 def collection(key, scheme = nil, view: 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? if scheme.nil? dependent_key = @current_type.as_key.dup dependent_key[1] = view unless @registry.has_key? dependent_key raise Errors::CollectionDefinitionNotFound.new(@current_type.override_suffix('json').to_s, @current_type.view(view).override_suffix('json').to_s) end scheme = @registry[dependent_key] end 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, registry: @registry, current_type: @current_type, &block), optional: optional) end |
#empty ⇒ Object
Mark object as a valid empty object
444 445 |
# File 'lib/media_types/scheme.rb', line 444 def empty end |
#index(optional: false) ⇒ Object
Expect an index of links
384 385 386 387 388 |
# File 'lib/media_types/scheme.rb', line 384 def index(optional: false) collection(:_links, optional: optional) do link :_self end end |
#inspect(indentation = 0) ⇒ Object
447 448 449 450 451 452 453 454 |
# File 'lib/media_types/scheme.rb', line 447 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
424 425 426 427 428 429 430 |
# File 'lib/media_types/scheme.rb', line 424 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
283 284 285 286 |
# File 'lib/media_types/scheme.rb', line 283 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!
309 310 311 |
# File 'lib/media_types/scheme.rb', line 309 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
469 470 471 |
# File 'lib/media_types/scheme.rb', line 469 def remove_current_dir_from_stack(stack) stack.reject { |location| location.path.include?(__dir__) } end |
#run_fixture_validations(expect_symbol_keys, backtrace = []) ⇒ Object
506 507 508 509 510 511 512 513 514 |
# File 'lib/media_types/scheme.rb', line 506 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
123 124 125 126 127 128 129 |
# File 'lib/media_types/scheme.rb', line 123 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
149 150 151 152 153 154 155 156 |
# File 'lib/media_types/scheme.rb', line 149 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
161 162 163 164 165 |
# File 'lib/media_types/scheme.rb', line 161 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
497 498 499 500 501 502 503 504 |
# File 'lib/media_types/scheme.rb', line 497 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
516 517 518 519 520 521 522 523 524 525 526 527 528 |
# File 'lib/media_types/scheme.rb', line 516 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, loose: fixture_data.loose) 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
484 485 486 487 488 489 490 491 492 493 494 495 |
# File 'lib/media_types/scheme.rb', line 484 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
473 474 475 476 477 478 479 480 481 482 |
# File 'lib/media_types/scheme.rb', line 473 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 |