Repository URL to install this package:
|
Version:
0.8.0 ▾
|
module JSONAPI
module Exceptions
class Error < RuntimeError; end
class InternalServerError < Error
attr_accessor :exception
def initialize(exception)
@exception = exception
end
def errors
unless Rails.env.production?
meta = Hash.new
meta[:exception] = exception.message
meta[:backtrace] = exception.backtrace
end
[JSONAPI::Error.new(code: JSONAPI::INTERNAL_SERVER_ERROR,
status: :internal_server_error,
title: I18n.t('jsonapi-resources.exceptions.internal_server_error.title',
default: 'Internal Server Error'),
detail: I18n.t('jsonapi-resources.exceptions.internal_server_error.detail',
default: 'Internal Server Error'),
meta: meta)]
end
end
class InvalidResource < Error
attr_accessor :resource
def initialize(resource)
@resource = resource
end
def errors
[JSONAPI::Error.new(code: JSONAPI::INVALID_RESOURCE,
status: :bad_request,
title: I18n.t('jsonapi-resources.exceptions.invalid_resource.title',
default: 'Invalid resource'),
detail: I18n.t('jsonapi-resources.exceptions.invalid_resource.detail',
default: "#{resource} is not a valid resource.", resource: resource))]
end
end
class RecordNotFound < Error
attr_accessor :id
def initialize(id)
@id = id
end
def errors
[JSONAPI::Error.new(code: JSONAPI::RECORD_NOT_FOUND,
status: :not_found,
title: I18n.translate('jsonapi-resources.exceptions.record_not_found.title',
default: 'Record not found'),
detail: I18n.translate('jsonapi-resources.exceptions.record_not_found.detail',
default: "The record identified by #{id} could not be found.", id: id))]
end
end
class UnsupportedMediaTypeError < Error
attr_accessor :media_type
def initialize(media_type)
@media_type = media_type
end
def errors
[JSONAPI::Error.new(code: JSONAPI::UNSUPPORTED_MEDIA_TYPE,
status: :unsupported_media_type,
title: I18n.translate('jsonapi-resources.exceptions.unsupported_media_type.title',
default: 'Unsupported media type'),
detail: I18n.translate('jsonapi-resources.exceptions.unsupported_media_type.detail',
default: "All requests that create or update must use the '#{JSONAPI::MEDIA_TYPE}' Content-Type. This request specified '#{media_type}'.",
needed_media_type: JSONAPI::MEDIA_TYPE,
media_type: media_type))]
end
end
class HasManyRelationExists < Error
attr_accessor :id
def initialize(id)
@id = id
end
def errors
[JSONAPI::Error.new(code: JSONAPI::RELATION_EXISTS,
status: :bad_request,
title: I18n.translate('jsonapi-resources.exceptions.has_many_relation.title',
default: 'Relation exists'),
detail: I18n.translate('jsonapi-resources.exceptions.has_many_relation.detail',
default: "The relation to #{id} already exists.",
id: id))]
end
end
class ToManySetReplacementForbidden < Error
def errors
[JSONAPI::Error.new(code: JSONAPI::FORBIDDEN,
status: :forbidden,
title: I18n.translate('jsonapi-resources.exceptions.to_many_set_replacement_forbidden.title',
default: 'Complete replacement forbidden'),
detail: I18n.translate('jsonapi-resources.exceptions.to_many_set_replacement_forbidden.detail',
default: 'Complete replacement forbidden for this relationship'))]
end
end
class InvalidFiltersSyntax < Error
attr_accessor :filters
def initialize(filters)
@filters = filters
end
def errors
[JSONAPI::Error.new(code: JSONAPI::INVALID_FILTERS_SYNTAX,
status: :bad_request,
title: I18n.translate('jsonapi-resources.exceptions.invalid_filter_syntax.title',
default: 'Invalid filters syntax'),
detail: I18n.translate('jsonapi-resources.exceptions.invalid_filter_syntax.detail',
default: "#{filters} is not a valid syntax for filtering.",
filters: filters))]
end
end
class FilterNotAllowed < Error
attr_accessor :filter
def initialize(filter)
@filter = filter
end
def errors
[JSONAPI::Error.new(code: JSONAPI::FILTER_NOT_ALLOWED,
status: :bad_request,
title: I18n.translate('jsonapi-resources.exceptions.filter_not_allowed.title',
default: 'Filter not allowed'),
detail: I18n.translate('jsonapi-resources.exceptions.filter_not_allowed.detail',
default: "#{filter} is not allowed.", filter: filter))]
end
end
class InvalidFilterValue < Error
attr_accessor :filter, :value
def initialize(filter, value)
@filter = filter
@value = value
end
def errors
[JSONAPI::Error.new(code: JSONAPI::INVALID_FILTER_VALUE,
status: :bad_request,
title: I18n.translate('jsonapi-resources.exceptions.invalid_filter_value.title',
default: 'Invalid filter value'),
detail: I18n.translate('jsonapi-resources.exceptions.invalid_filter_value.detail',
default: "#{value} is not a valid value for #{filter}.",
value: value, filter: filter))]
end
end
class InvalidFieldValue < Error
attr_accessor :field, :value
def initialize(field, value)
@field = field
@value = value
end
def errors
[JSONAPI::Error.new(code: JSONAPI::INVALID_FIELD_VALUE,
status: :bad_request,
title: I18n.translate('jsonapi-resources.exceptions.invalid_field_value.title',
default: 'Invalid field value'),
detail: I18n.translate('jsonapi-resources.exceptions.invalid_field_value.detail',
default: "#{value} is not a valid value for #{field}.",
value: value, field: field))]
end
end
class InvalidFieldFormat < Error
def errors
[JSONAPI::Error.new(code: JSONAPI::INVALID_FIELD_FORMAT,
status: :bad_request,
title: I18n.translate('jsonapi-resources.exceptions.invalid_field_format.title',
default: 'Invalid field format'),
detail: I18n.translate('jsonapi-resources.exceptions.invalid_field_format.detail',
default: 'Fields must specify a type.'))]
end
end
class InvalidLinksObject < Error
def errors
[JSONAPI::Error.new(code: JSONAPI::INVALID_LINKS_OBJECT,
status: :bad_request,
title: I18n.translate('jsonapi-resources.exceptions.invalid_links_object.title',
default: 'Invalid Links Object'),
detail: I18n.translate('jsonapi-resources.exceptions.invalid_links_object.detail',
default: 'Data is not a valid Links Object.'))]
end
end
class TypeMismatch < Error
attr_accessor :type
def initialize(type)
@type = type
end
def errors
[JSONAPI::Error.new(code: JSONAPI::TYPE_MISMATCH,
status: :bad_request,
title: I18n.translate('jsonapi-resources.exceptions.type_mismatch.title',
default: 'Type Mismatch'),
detail: I18n.translate('jsonapi-resources.exceptions.type_mismatch.detail',
default: "#{type} is not a valid type for this operation.", type: type))]
end
end
class InvalidField < Error
attr_accessor :field, :type
def initialize(type, field)
@field = field
@type = type
end
def errors
[JSONAPI::Error.new(code: JSONAPI::INVALID_FIELD,
status: :bad_request,
title: I18n.translate('jsonapi-resources.exceptions.invalid_field.title',
default: 'Invalid field'),
detail: I18n.translate('jsonapi-resources.exceptions.invalid_field.detail',
default: "#{field} is not a valid field for #{type}.",
field: field, type: type))]
end
end
class InvalidInclude < Error
attr_accessor :relationship, :resource
def initialize(resource, relationship)
@resource = resource
@relationship = relationship
end
def errors
[JSONAPI::Error.new(code: JSONAPI::INVALID_INCLUDE,
status: :bad_request,
title: I18n.translate('jsonapi-resources.exceptions.invalid_include.title',
default: 'Invalid field'),
detail: I18n.translate('jsonapi-resources.exceptions.invalid_include.detail',
default: "#{relationship} is not a valid relationship of #{resource}",
relationship: relationship, resource: resource))]
end
end
class InvalidSortCriteria < Error
attr_accessor :sort_criteria, :resource
def initialize(resource, sort_criteria)
@resource = resource
@sort_criteria = sort_criteria
end
def errors
[JSONAPI::Error.new(code: JSONAPI::INVALID_SORT_CRITERIA,
status: :bad_request,
title: I18n.translate('jsonapi-resources.exceptions.invalid_sort_criteria.title',
default: 'Invalid sort criteria'),
detail: I18n.translate('jsonapi-resources.exceptions.invalid_sort_criteria.detail',
default: "#{sort_criteria} is not a valid sort criteria for #{resource}",
sort_criteria: sort_criteria, resource: resource))]
end
end
class ParametersNotAllowed < Error
attr_accessor :params
def initialize(params)
@params = params
end
def errors
params.collect do |param|
JSONAPI::Error.new(code: JSONAPI::PARAM_NOT_ALLOWED,
status: :bad_request,
title: I18n.translate('jsonapi-resources.exceptions.parameters_not_allowed.title',
default: 'Param not allowed'),
detail: I18n.translate('jsonapi-resources.exceptions.parameters_not_allowed.detail',
default: "#{param} is not allowed.", param: param))
end
end
end
class ParameterMissing < Error
attr_accessor :param
def initialize(param)
@param = param
end
def errors
[JSONAPI::Error.new(code: JSONAPI::PARAM_MISSING,
status: :bad_request,
title: I18n.translate('jsonapi-resources.exceptions.parameter_missing.title',
default: 'Missing Parameter'),
detail: I18n.translate('jsonapi-resources.exceptions.parameter_missing.detail',
default: "The required parameter, #{param}, is missing.", param: param))]
end
end
class CountMismatch < Error
def errors
[JSONAPI::Error.new(code: JSONAPI::COUNT_MISMATCH,
status: :bad_request,
title: I18n.translate('jsonapi-resources.exceptions.count_mismatch.title',
default: 'Count to key mismatch'),
detail: I18n.translate('jsonapi-resources.exceptions.count_mismatch.detail',
default: 'The resource collection does not contain the same number of objects as the number of keys.'))]
end
end
class KeyNotIncludedInURL < Error
attr_accessor :key
def initialize(key)
@key = key
end
def errors
[JSONAPI::Error.new(code: JSONAPI::KEY_NOT_INCLUDED_IN_URL,
status: :bad_request,
title: I18n.translate('jsonapi-resources.exceptions.key_not_included_in_url.title',
default: 'Key is not included in URL'),
detail: I18n.translate('jsonapi-resources.exceptions.key_not_included_in_url.detail',
default: "The URL does not support the key #{key}",
key: key))]
end
end
class MissingKey < Error
def errors
[JSONAPI::Error.new(code: JSONAPI::KEY_ORDER_MISMATCH,
status: :bad_request,
title: I18n.translate('jsonapi-resources.exceptions.missing_key.title',
default: 'A key is required'),
detail: I18n.translate('jsonapi-resources.exceptions.missing_key.detail',
default: 'The resource object does not contain a key.'))]
end
end
class RecordLocked < Error
attr_accessor :message
def initialize(message)
@message = message
end
def errors
[JSONAPI::Error.new(code: JSONAPI::LOCKED,
status: :locked,
title: I18n.translate('jsonapi-resources.exceptions.record_locked.title',
default: 'Locked resource'),
detail: "#{message}")]
end
end
class ValidationErrors < Error
attr_reader :error_messages, :error_metadata, :resource_relationships
def initialize(resource)
@error_messages = resource.model_error_messages
@error_metadata = resource.validation_error_metadata
@resource_relationships = resource.class._relationships.keys
@key_formatter = JSONAPI.configuration.key_formatter
end
def format_key(key)
@key_formatter.format(key)
end
def errors
error_messages.flat_map do |attr_key, messages|
messages.map { |message| json_api_error(attr_key, message) }
end
end
private
def json_api_error(attr_key, message)
JSONAPI::Error.new(code: JSONAPI::VALIDATION_ERROR,
status: :unprocessable_entity,
title: message,
detail: "#{format_key(attr_key)} - #{message}",
source: { pointer: pointer(attr_key) },
meta: metadata_for(attr_key, message))
end
def metadata_for(attr_key, message)
return if error_metadata.nil?
error_metadata[attr_key] ? error_metadata[attr_key][message] : nil
end
def pointer(attr_or_relationship_name)
formatted_attr_or_relationship_name = format_key(attr_or_relationship_name)
if resource_relationships.include?(attr_or_relationship_name)
"/data/relationships/#{formatted_attr_or_relationship_name}"
else
"/data/attributes/#{formatted_attr_or_relationship_name}"
end
end
end
class SaveFailed < Error
def errors
[JSONAPI::Error.new(code: JSONAPI::SAVE_FAILED,
status: :unprocessable_entity,
title: I18n.translate('jsonapi-resources.exceptions.save_failed.title',
default: 'Save failed or was cancelled'),
detail: I18n.translate('jsonapi-resources.exceptions.save_failed.detail',
default: 'Save failed or was cancelled'))]
end
end
class InvalidPageObject < Error
def errors
[JSONAPI::Error.new(code: JSONAPI::INVALID_PAGE_OBJECT,
status: :bad_request,
title: I18n.translate('jsonapi-resources.exceptions.invalid_page_object.title',
default: 'Invalid Page Object'),
detail: I18n.translate('jsonapi-resources.exceptions.invalid_page_object.detail',
default: 'Invalid Page Object.'))]
end
end
class PageParametersNotAllowed < Error
attr_accessor :params
def initialize(params)
@params = params
end
def errors
params.collect do |param|
JSONAPI::Error.new(code: JSONAPI::PARAM_NOT_ALLOWED,
status: :bad_request,
title: I18n.translate('jsonapi-resources.exceptions.page_parameters_not_allowed.title',
default: 'Page parameter not allowed'),
detail: I18n.translate('jsonapi-resources.exceptions.page_parameters_not_allowed.detail',
default: "#{param} is not an allowed page parameter.",
param: param))
end
end
end
class InvalidPageValue < Error
attr_accessor :page, :value
def initialize(page, value, msg = nil)
@page = page
@value = value
@msg = msg || I18n.translate('jsonapi-resources.exceptions.invalid_page_value.detail',
default: "#{value} is not a valid value for #{page} page parameter.",
value: value, page: page)
end
def errors
[JSONAPI::Error.new(code: JSONAPI::INVALID_PAGE_VALUE,
status: :bad_request,
title: I18n.translate('jsonapi-resources.exceptions.invalid_page_value.title',
default: 'Invalid page value'),
detail: @msg)]
end
end
end
end