class Hoodoo::ErrorDescriptions
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 )
Public Class Methods
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
# 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
Public Instance Methods
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’.
# 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
”
# 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
Is the given error code recognised? Returns true
if so, else false
.
code
-
Error code in full, e.g. +generic.invalid_state’.
# File lib/hoodoo/errors/error_descriptions.rb, line 152 def recognised?( code ) @descriptions.has_key?( code ) end