The JSON API docs currently state (I'm not sure if they said this before JSON API 1.0):
A document MUST contain at least one of the following top-level members:
data: containing the document's "primary data"
errors: containing an array of error objects
meta: non-standard meta-information.
The members data and errors MUST NOT coexist in the same document.
Is there a way to render the errors member in master / v0.10.0.rc1?
@remear it's a implementation of 1.0
We haven't updated AMS yet, the actual supported version is RC4, we might update it this week but don't take it for granted :smile:
Great! Would it be possible to leave this issue open until it's resolved and reference it in commits so others can follow along. I'd love to help test this as soon as it becomes available.
I think what you want here is pseudo-code
if success
render json: model
else
render json: model.errors, root: "errors" # or maybe roll-your own error serializer and model. Just mix in ActiveModel::Serialization
end
right?
That's one way. For a rough example, what if I wanted to do this from rack with:
def respond_400(errors)
serializer = ActiveModel::Serializer::ArraySerializer.new(errors, serializer: ErrorSerializer)
response = ActiveModel::Serializer::Adapter.create(serializer).to_json
[400, {'Content-Type' => 'application/vnd.api+json'}, [response]]
end
I wasn't sure how to get root in there.
Oh. you probably don't want to do that for a couple of reasons
ErrorsController.action(:show).call(env.merge(something)) (this will skip the rest of the call stack, see actioncontroller::metalFollowing @bf4's suggestion the structure still isn't in accordance with the JSON API specifications example and suggested structure. Here's an example structure from jsonapi.org:
{
"errors": [
{
"status": "422",
"source": { "pointer": "/data/attributes/first-name" },
"title": "Invalid Attribute",
"detail": "First name must contain at least three characters."
}
]
}
Using the following code I can still follow the JSON API requirements but it still isn't even close to the suggested structure above, which would be much more powerful:
if object.save
render json: object, status: :created, location: object
else
render json: { errors: object.errors }, status: :unprocessable_entity
end
Example error output:
{
"errors": {
"first_name": ["can't be blank", "is too short (minimum is 3 characters)", "is invalid"]
}
}
I'd love to see this be part of this gem before Release of 0.10! :+1:
@bf4: Thank you, looks like good progress. I'm currently using the https://github.com/joaomdmoura/active_model_serializers/tree/deserializer-implementation branch though since I really need the deserializers, so I will have to wait until both come to complete fruition and get merged.
I might be mistaken but my feeling when reading through the other threads was that this issue is either already solved or a duplicate, isn't it?
@Dschee I would say it can be done, just not explicitly supported, esp JsonApi, that's more work. In fact, it led me to create a json api errors examples on their examples page.. which is also why so many of the features are still unchecked in that pr :)
For rehydrating, take a look at some of the libs on http://jsonapi.org/implementations/
Would love a few eyes on the PR https://github.com/rails-api/active_model_serializers/issues/1004
Wanted to copy the PR description from #1004 to track further changes / remaining TODOs
Courtesy of @bf4
Requires explicit passing of Error serializer
# POST /api/{plural_resource_name}
def create
set_resource(resource_class.new(resource_params))
if get_resource.save
render :show, status: :created, adapter: :json_api
else
render json: get_resource.errors, status: :unprocessable_entity, adapter: :json_api, serializer: ActiveModel::Serializer::ErrorSerializer
end
end
PR TODOS:
jsonapi/errors.mdSerializing errors is different from resources.
ActiveModel::Error, which we'd want to call model.errors.messages on.ActiveModel::Error is necessarily a collection of error objects, each with it's own 'source' and 'detail'test/action_controller/json_api/errors_test.rbtest/action_controller/rescue_from_test.rbrescue_with_handler, handle_exceptions](https://github.com/rails-api/active_model_serializers/pull/1004#discussion_r46471845)ref:
Something I'll probably work on soon is automatically detecting the existence of errors of swapping out what was going to be used to render the object, with the errors serializer. This should probably be an opt-in feature
I implemented that in the pr and backed it out. We don't have enough
control in the controller to do it well, esp the status code
Better to focus elsewhere I think
You can see it in the commit history
On Mon, Mar 7, 2016 at 6:31 AM L. Preston Sego III [email protected]
wrote:
Something I'll probably work on soon is automatically detecting the
existence of errors of swapping out what was going to be used to render the
object, with the errors serializer. This should probably be an opt-in
feature—
Reply to this email directly or view it on GitHub
https://github.com/rails-api/active_model_serializers/issues/933#issuecomment-193232069
.
can the errors objects have added data to them? like by default, 422, but if we want to add a custom error to :base, maybe add 401 to some property on that particular error object? that way the error codes are still managed outside of AMS
It's a goal but current impl ia sufficient. Doing it right will require lots of new objects and APIs and tighter rails integration. I think of it as phase two or so
B mobile phone
On Mar 7, 2016, at 1:16 PM, L. Preston Sego III [email protected] wrote:
can the errors objects have added data to them? like by default, 422, but if we want to add a custom error to :base, maybe add 401 to some property on that particular error object? that way the error codes are still managed outside of AMS
—
Reply to this email directly or view it on GitHub.
Any update on the remaining features?
there's this:
ActiveModel::Serializer::ErrorSerializer
This is what I use in my app:
render json: model, status: 422, serializer: ActiveModel::Serializer::ErrorSerializer
I use the same render approach but that doesn't include the HTTP status code inside the body as JSONAPI suggests, only in the header.
ah, I see. in the examples, jsonapi gives a different status code per error. http://jsonapi.org/examples/#error-objects (or the capability to).
I'm not sure how this would work with the default ErrorSerializer.
You could probably have a request-level errors object to keep track of errors during a request and append to that list as things happen, and then if the list contains errors, render that instead of the resource?
That would add a lot of extra workload both on the implementation and on the actual use of serializers.
Another idea would be to make use of the new feature in Rails 5.0.1 . We could assign http statuses to the new details attribute of error and display them per error.
That would add a lot of extra workload both on the implementation and on the actual use of serializers.
Yeah, I don't think adding per-error status adds a whole lot of value anyway.
I think a request should short-circuit immediately when the first error is hit.
Another idea would be to make use of the new feature in Rails 5.0.1 .
If anything, I think that would just clean up the existing error serializer.
doesn't include the HTTP status code inside the body as JSONAPI suggests, only in the header.
suggests, not require
I couldn't figure out a clean way to do it and it's been a while and no one has felt the need to add more error serializing features, or fix some bugs in my lame pointer code.
In brief, in order to provide richer errors, we need tighter integration with the rendering context like jsonapi-resources has.
I'd be happy to start a new issue to discuss specific feature requests. Otherwise, this is really just issue necromancy.
Arguably the issue could be a placeholder for all errors discussions, but I'm going to close the issue now, and not lock it in case anyone has a good reason to continue discussion in this issue specifically.
Most helpful comment
This is what I use in my app: