A collection of error descriptions. API service implementations create one of these, which self-declares platform and generic error domain codes. A simple DSL is available to declare service-specific errors. Since the middleware is responsible for instantiating an error collection inside a response object which service implementations use to signal error conditions, the service's interface class uses the interface description DSL to call through to here behind the scenes; for example:
class TransactionImplementation < Hoodoo::Services::Implementation
# ...
end
class TransactionInterface < Hoodoo::Services::Interface
interface :Transaction do
endpoint :transactions, TransactionImplementation
errors_for 'transaction' do
error 'duplicate_transaction', status: 409, message: 'Duplicate transaction', :required => [ :client_uid ]
end
end
end
The errors_for
method takes the domain of the error as a string - the part that comes
before the “.
” in error codes. Then a series of
error
calls describe the individual error codes. See Hoodoo::ErrorDescriptions::DomainDescriptions#error
for details.
An instance of the Hoodoo::ErrorDescriptions class gets built behind the scenes as part of the service interface description. This is found by the middleware and passed to a Hoodoo::Errors constructor. The result is stored in a Hoodoo::Services::Response instance and passed to handler methods in the service's Hoodoo::Services::Implementation subclass for each request. Service implementations access the errors collection through Hoodoo::Services::Response#errors and can then add errors using the generic or platform domains, or whatever additional custom domain(s) they defined in the service interface subclass.
For direct callers (e.g. the middleware), there is a shorthand form to invoke the DSL where the constructor is used in the same way as errors_for:
ERROR_DESCRIPTIONS = Hoodoo::ErrorDescriptions.new( 'transaction' ) do
error 'duplicate_transaction', status: 409, message: 'Duplicate transaction', :required => [ :client_uid ]
end
Either way,
As per the example above, services can share an instance across requests (and threads) via a class's variable if the descriptions don't change. You would use the descriptions to inform a Hoodoo::Errors instance of the available codes and their requirements:
@errors = Hoodoo::Errors.new( ERROR_DESCRIPTIONS )
- D
- E
- N
- R
Create an instance, self-declaring platform
and
generic
domain errors. You can optionally call the constructor
with an error domain and code block, to declare errors all in one go rather
than making a separate call to errors_for (but both
approaches are valid).
domain
-
Optional domain, just as used in errors_for
- &block
-
Optional block, just as used in errors_for
Source: show
# File lib/hoodoo/errors/error_descriptions.rb, line 80 def initialize( domain = nil, &block ) @descriptions = {} # Up to date at Preview Release 9, 2014-11-10. errors_for 'platform' do error 'not_found', status: 404, message: 'Not found', reference: [ :entity_name ] error 'malformed', status: 422, message: 'Malformed request' error 'invalid_session', status: 401, message: 'Invalid session' error 'forbidden', status: 403, message: 'Action not authorized' error 'method_not_allowed', status: 405, message: 'Method not allowed' error 'timeout', status: 408, message: 'Request timeout' error 'fault', status: 500, message: 'Internal error', reference: [ :exception ] end # Up to date at Preview Release 9, 2014-11-10. errors_for 'generic' do error 'not_found', status: 404, message: 'Resource not found', reference: [ :ident ] error 'contemporary_exists', status: 404, message: 'Contemporary record exists', reference: [ :ident ] error 'malformed', status: 422, message: 'Malformed payload' error 'required_field_missing', status: 422, message: 'Required field missing', reference: [ :field_name ] error 'invalid_string', status: 422, message: 'Invalid string format', reference: [ :field_name ] error 'invalid_integer', status: 422, message: 'Invalid integer format', reference: [ :field_name ] error 'invalid_float', status: 422, message: 'Invalid float format', reference: [ :field_name ] error 'invalid_decimal', status: 422, message: 'Invalid decimal format', reference: [ :field_name ] error 'invalid_boolean', status: 422, message: 'Invalid boolean format', reference: [ :field_name ] error 'invalid_enum', status: 422, message: 'Invalid enumeration', reference: [ :field_name ] error 'invalid_date', status: 422, message: 'Invalid date specifier', reference: [ :field_name ] error 'invalid_time', status: 422, message: 'Invalid time specifier', reference: [ :field_name ] error 'invalid_datetime', status: 422, message: 'Invalid date-time specifier', reference: [ :field_name ] error 'invalid_uuid', status: 422, message: 'Invalid UUID', reference: [ :field_name ] error 'invalid_array', status: 422, message: 'Invalid array', reference: [ :field_name ] error 'invalid_object', status: 422, message: 'Invalid object', reference: [ :field_name ] error 'invalid_hash', status: 422, message: 'Invalid hash', reference: [ :field_name ] error 'invalid_duplication', status: 422, message: 'Duplicates not allowed', reference: [ :field_name ] error 'invalid_state', status: 422, message: 'State transition not allowed', reference: [ :destination_state ] error 'invalid_parameters', status: 422, message: 'Invalid parameters' error 'mutually_exclusive', status: 422, message: 'Mutually exclusive parameters', reference: [ :field_names ] end # Add caller's custom errors for the shorthand form, if provided. if ( domain != nil && domain != '' && block_given?() ) errors_for( domain, &block ) end end
Return the options description hash, as passed to error
calls
in the block given to errors_for, for the
given code.
code
-
Error code in full, e.g. +generic.invalid_state'.
Source: show
# File lib/hoodoo/errors/error_descriptions.rb, line 161 def describe( code ) @descriptions[ code ] end
Implement the collection's part of the small DSL used for error
declaration. Call here, passing the error domain (usually the singular
service name or resource name, e.g. “transaction
” and defined
by the part of the platform API the service is implementing) and a block.
The block makes one or more “error
” calls, which actually end
up calling Hoodoo::ErrorDescriptions::DomainDescriptions#error
behind the scenes.
See the implementation of initialize for a worked example.
domain
-
Error domain, e.g.
platform
,transaction
- &block
-
Block which makes one or more calls to “
error
”
Source: show
# File lib/hoodoo/errors/error_descriptions.rb, line 141 def errors_for( domain, &block ) domain_descriptions = Hoodoo::ErrorDescriptions::DomainDescriptions.new( domain ) domain_descriptions.instance_eval( &block ) @descriptions.merge!( domain_descriptions.descriptions ) end