diff --git a/lib/jsonapi/exceptions.rb b/lib/jsonapi/exceptions.rb index 4aae8f279..6c44de76b 100644 --- a/lib/jsonapi/exceptions.rb +++ b/lib/jsonapi/exceptions.rb @@ -448,11 +448,12 @@ def errors end class ValidationErrors < Error - attr_reader :error_messages, :error_metadata, :resource_relationships + attr_reader :error_messages, :error_metadata, :resource_relationships, :resource_class def initialize(resource, error_object_overrides = {}) @error_messages = resource.model_error_messages @error_metadata = resource.validation_error_metadata + @resource_class = resource.class @resource_relationships = resource.class._relationships.keys @key_formatter = JSONAPI.configuration.key_formatter super(error_object_overrides) @@ -474,7 +475,7 @@ def json_api_error(attr_key, message) create_error_object(code: JSONAPI::VALIDATION_ERROR, status: :unprocessable_entity, title: message, - detail: "#{format_key(attr_key)} - #{message}", + detail: detail(attr_key, message), source: { pointer: pointer(attr_key) }, meta: metadata_for(attr_key, message)) end @@ -484,7 +485,12 @@ def metadata_for(attr_key, message) error_metadata[attr_key] ? error_metadata[attr_key][message] : nil end + def detail(attr_key, message) + general_error?(attr_key) ? message : "#{format_key(attr_key)} - #{message}" + end + def pointer(attr_or_relationship_name) + return '/data' if general_error?(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}" @@ -492,6 +498,10 @@ def pointer(attr_or_relationship_name) "/data/attributes/#{formatted_attr_or_relationship_name}" end end + + def general_error?(attr_key) + attr_key.to_sym == :base && !resource_class._has_attribute?(attr_key) + end end class SaveFailed < Error diff --git a/lib/jsonapi/resource.rb b/lib/jsonapi/resource.rb index fb534b5de..6710b3eb1 100644 --- a/lib/jsonapi/resource.rb +++ b/lib/jsonapi/resource.rb @@ -911,6 +911,10 @@ def _attribute_options(attr) default_attribute_options.merge(@_attributes[attr]) end + def _has_attribute?(attr) + @_attributes.keys.include?(attr.to_sym) + end + def _updatable_relationships @_relationships.map { |key, _relationship| key } end