Search code examples
ruby-on-railsjsonserializationjson-api

Rails JSON API - json doesn't contain errors


I am rendering an array of ActiveRecord items. Each of them has passed through valid? method - so the errors are already defined. I render the array like this:

render json: array_of_objects

I have ActiveModelSerializers.config.adapter = :json_api set.

But the outcome json lacks errors - it contains only the data of objects.

How can I retrieve json (of each one by one or all at once) items with the errors included?


Solution

  • The JSON API specification is very fuzzy when it comes to how validation errors should be handled:

    A server MAY choose to stop processing as soon as a problem is encountered, or it MAY continue processing and encounter multiple problems. For instance, a server might process multiple attributes and then return multiple validation problems in a single response.

    When a server encounters multiple problems for a single request, the most generally applicable HTTP error code SHOULD be used in the response. For instance, 400 Bad Request might be appropriate for multiple 4xx errors or 500 Internal Server Error might be appropriate for multiple 5xx errors.

    Error objects can be included - but they should be included at the top level of the document:

    Error objects provide additional information about problems encountered while performing an operation. Error objects MUST be returned as an array keyed by errors in the top level of a JSON API document.

    ActiveModel::Serializers JSON API Adapter does not provide error object handling as it would be far to complex to handle the various use cases.

    Especially your case as you seem to be creating/modifying several records at once. In the case of creating its especially tricky since you need to link the error to the attribute in the input that caused the error since there is no id to point to.

    You can possibly roll your own serializer:

    class PostSerializer < ActiveModel::Serializer
      attributes :title, :body, :errors
    
      def errors
        object.errors.full_messages if object.errors.any?
      end
    end