Serializing the errors hash in ActiveModel::Serializer

后端 未结 4 1157
囚心锁ツ
囚心锁ツ 2021-02-08 13:45

I\'m using ActiveModel::Serializer to customize the JSON responses for my API. This works fine in most cases, except when it fails to save a model successfully.

For exa

相关标签:
4条回答
  • 2021-02-08 13:55

    I believe that the problem in this case is that for the failed status you won't call render with an object, like for created status.

    You can use a custom Serializer when calling render, for this case you can probably use something like

    if resource.errors.any?
      render serializer: ErrorSerializer, json: {:status => 'failed', :errors => resource.errors}
    else
      render json: {:status => 'created', :object => resource}
    end
    

    Give it a try and keep us informed of the result :)

    0 讨论(0)
  • 2021-02-08 14:02

    I found this answer on this blog post ... which starts as such ...

    The default serialization of error states in Rails might not be what you want for your app. In that case, it’d be worth knowing how to write a custom serialization format for your needs. In my case, I am trying to match the JSON API format for errors. Here’s a potential implementation…

    Example validation error

    By default, Rails 4 will return an error serialization that looks like this (for a book model where title should always be present):

    {
      "title": [
        "can't be blank"
      ]
    }
    

    Create a custom error serializer

    In /serializers/error_serializer.rb ...

    module ErrorSerializer
    
      def self.serialize(errors)
        return if errors.nil?
    
        json = {}
        new_hash = errors.to_hash(true).map do |k, v|
          v.map do |msg|
            { id: k, title: msg }
          end
        end.flatten
        json[:errors] = new_hash
        json
      end
    end
    

    Use it in your controller

    Now include ErrorSerializer in your controller so that you can do something like this using the errors hash i.e. render: json: ErrorSerializer.serialize(book.errors)

    Result

    {
      "errors": [
        {
          "id": "title",
          "title": "Title can't be blank"
        }
      ]
    }
    

    Read the actual post for the deets.

    0 讨论(0)
  • 2021-02-08 14:03

    The ErrorsSerializer doesn't work because of how responders create json response for errors:

    def json_resource_errors
      { errors: resource.errors }
    end
    

    (rails < 4.2 https://github.com/rails/rails/blob/4-1-stable/actionpack/lib/action_controller/metal/responder.rb#L290 for newer rails, responders have been extracted to https://github.com/plataformatec/responders/blob/master/lib/action_controller/responder.rb#L288)

    one way of dealing with this is to override this method for responders. Put this code in your config initializers:

    # config/initializers/action_controller_responder.rb
    module ActionController
      class Responder
        def json_resource_errors
          resource.errors
        end
      end
    end
    

    Then your serializer will work for resource errors.

    0 讨论(0)
  • 2021-02-08 14:19

    The class name of resource.errors is ActiveModel::Errors so you have to define you class as ActiveModel::ErrorsSerializer.

    Ref: source code

    0 讨论(0)
提交回复
热议问题