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
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 :)
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.
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.
The class name of resource.errors is ActiveModel::Errors
so you have to define you class as
ActiveModel::ErrorsSerializer
.
Ref: source code