class JSONAPI::Utils::Exceptions::ActiveRecord
Attributes
Public Class Methods
Construct an error decorator over ActiveRecord
objects.
@param object [ActiveRecord::Base] Invalid ActiveRecord
object.
e.g.: User.new(name: nil).tap(&:save)
@param resource_klass [JSONAPI::Resource] Resource class to be used for reflection.
e.g.: UserResuource
@return [JSONAPI::Utils::Exceptions::ActiveRecord]
@api public
# File lib/jsonapi/utils/exceptions/active_record.rb, line 18 def initialize(object, resource_klass, context) @object = object @resource = resource_klass.new(object, context) # Need to reflect on resource's relationships for error reporting. @relationships = resource_klass._relationships.values @relationship_names = @relationships.map(&:name).map(&:to_sym) @foreign_keys = @relationships.map(&:foreign_key).map(&:to_sym) @resource_key_for = {} @formatted_key = {} end
Public Instance Methods
Decorate errors for AR invalid objects.
@note That's the method used by formatters to build the response's error body.
@return [Array]
@api public
# File lib/jsonapi/utils/exceptions/active_record.rb, line 37 def errors object.errors.messages.flat_map do |field, messages| messages.map.with_index do |message, index| build_error(field, message, index) end end end
Private Instance Methods
Turn AR error into JSONAPI::Error.
@param field [Symbol] Name of the invalid field
e.g.: :title
@param message [String] Error message
e.g.: "can't be blank"
@param index [Integer] Index of the error detail
@return [JSONAPI::Error]
@api private
# File lib/jsonapi/utils/exceptions/active_record.rb, line 60 def build_error(field, message, index = 0) error = error_base .merge( id: id_member(field, index), title: message, detail: detail_member(field, message) ).merge(source_member(field)) JSONAPI::Error.new(error) end
Build the “detail” member value for the JSON API error object.
e.g.: :first_name, "can't be blank" => "First name can't be blank"
@param field [Symbol] Name of the invalid field
e.g.: :first_name
@return [String]
@api private
# File lib/jsonapi/utils/exceptions/active_record.rb, line 148 def detail_member(field, message) return message if field == :base resource_key = resource_key_for(field) [translation_for(resource_key), message].join(' ') end
Return the base data used for all errors of this kind.
@return [Hash]
@api private
# File lib/jsonapi/utils/exceptions/active_record.rb, line 188 def error_base { code: JSONAPI::VALIDATION_ERROR, status: :unprocessable_entity } end
Build the “id” member value for the JSON API error object.
e.g.: for :first_name, :too_short => "first-name#too-short"
@note The returned value depends on the key formatter type defined
via configuration, e.g.: config.json_key_format = :dasherized_key
@param field [Symbol] Name of the invalid field
e.g.: :first_name
@param index [Integer] Index of the error detail
@return [String]
@api private
# File lib/jsonapi/utils/exceptions/active_record.rb, line 84 def id_member(field, index) [ key_format(field), key_format( object.errors.details .dig(field, index, :error) .to_s.downcase .split .join('_') ) ].join('#') end
Bring the formatted resource key for a given field.
e.g.: for :first_name => :"first-name"
@note The returned value depends on the key formatter type defined
via configuration, e.g.: config.json_key_format = :dasherized_key
@param field [Symbol] Name of the invalid field
e.g.: :title
@return [Symbol]
@api private
# File lib/jsonapi/utils/exceptions/active_record.rb, line 109 def key_format(field) @formatted_key[field] ||= JSONAPI.configuration .key_formatter .format(resource_key_for(field)) .to_sym end
Return the resource's attribute or relationship key name for a given field name.
e.g.: :title => :title, :user_id => :author
@param field [Symbol] Name of the invalid field
e.g.: :title
@return [Symbol]
@api private
# File lib/jsonapi/utils/exceptions/active_record.rb, line 163 def resource_key_for(field) @resource_key_for[field] ||= begin return field unless foreign_keys.include?(field) relationships.find { |r| r.foreign_key == field }.name.to_sym end end
Build the “source” member value for the JSON API error object.
e.g.: :title => "/data/attributes/title"
@param field [Symbol] Name of the invalid field
e.g.: :title
@return [Hash]
@api private
# File lib/jsonapi/utils/exceptions/active_record.rb, line 125 def source_member(field) resource_key = resource_key_for(field) return {} unless field == :base || resource.fetchable_fields.include?(resource_key) id = key_format(field) pointer = if field == :base then '/data' elsif relationship_names.include?(resource_key) then "/data/relationships/#{id}" else "/data/attributes/#{id}" end { source: { pointer: pointer } } end
Turn the field name into human-friendly one.
e.g.: :first_name => "First name"
@param field [Symbol] Name of the invalid field
e.g.: :first_name
@return [String]
@api private
# File lib/jsonapi/utils/exceptions/active_record.rb, line 179 def translation_for(field) object.class.human_attribute_name(field) end