-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[RFC] JSON API Errors (Initial implementation and roadmap for full feature-set) #1004
Changes from all commits
0ba944d
dfe1626
96107c5
3d98637
e6ae34b
d03db81
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
[Back to Guides](../README.md) | ||
|
||
# [JSON API Errors](http://jsonapi.org/format/#errors) | ||
|
||
Rendering error documents requires specifying the error serializer(s): | ||
|
||
- Serializer: | ||
- For a single resource: `serializer: ActiveModel::Serializer::ErrorSerializer`. | ||
- For a collection: `serializer: ActiveModel::Serializer::ErrorsSerializer`, `each_serializer: ActiveModel::Serializer::ErrorSerializer`. | ||
|
||
The resource **MUST** have a non-empty associated `#errors` object. | ||
The `errors` object must have a `#messages` method that returns a hash of error name to array of | ||
descriptions. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As commented in the PR, I think it would be a good idea to add the requirement about There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @buren So, the problem is that I'm documenting how AMS works, not JSON API. I could add a link to the spec (like in #1004 (comment) ) somewhere in here or to https://github.com/rails-api/active_model_serializers/blob/master/docs/jsonapi/schema.md |
||
|
||
## Use in controllers | ||
|
||
```ruby | ||
resource = Profile.new(name: 'Name 1', | ||
description: 'Description 1', | ||
comments: 'Comments 1') | ||
resource.errors.add(:name, 'cannot be nil') | ||
resource.errors.add(:name, 'must be longer') | ||
resource.errors.add(:id, 'must be a uuid') | ||
|
||
render json: resource, status: 422, adapter: :json_api, serializer: ActiveModel::Serializer::ErrorSerializer | ||
# #=> | ||
# { :errors => | ||
# [ | ||
# { :source => { :pointer => '/data/attributes/name' }, :detail => 'cannot be nil' }, | ||
# { :source => { :pointer => '/data/attributes/name' }, :detail => 'must be longer' }, | ||
# { :source => { :pointer => '/data/attributes/id' }, :detail => 'must be a uuid' } | ||
# ] | ||
# }.to_json | ||
``` | ||
|
||
## Direct error document generation | ||
|
||
```ruby | ||
options = nil | ||
resource = ModelWithErrors.new | ||
resource.errors.add(:name, 'must be awesome') | ||
|
||
serializable_resource = ActiveModel::SerializableResource.new( | ||
resource, { | ||
serializer: ActiveModel::Serializer::ErrorSerializer, | ||
adapter: :json_api | ||
}) | ||
serializable_resource.as_json(options) | ||
# #=> | ||
# { | ||
# :errors => | ||
# [ | ||
# { :source => { :pointer => '/data/attributes/name' }, :detail => 'must be awesome' } | ||
# ] | ||
# } | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,8 @@ | ||
require 'thread_safe' | ||
require 'active_model/serializer/collection_serializer' | ||
require 'active_model/serializer/array_serializer' | ||
require 'active_model/serializer/error_serializer' | ||
require 'active_model/serializer/errors_serializer' | ||
require 'active_model/serializer/include_tree' | ||
require 'active_model/serializer/associations' | ||
require 'active_model/serializer/attributes' | ||
|
@@ -116,6 +118,10 @@ def initialize(object, options = {}) | |
end | ||
end | ||
|
||
def success? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what's the purpose of this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sentinel for rendering success vs failurr doc. Search diff for usage |
||
true | ||
end | ||
|
||
# Used by adapter as resource root. | ||
def json_key | ||
root || object.class.model_name.to_s.underscore | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
class ActiveModel::Serializer::ErrorSerializer < ActiveModel::Serializer | ||
# @return [Hash<field_name,Array<error_message>>] | ||
def as_json | ||
object.errors.messages | ||
end | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It doesn't really need to inherit from serializer at this point.. but for interface purposes I am |
||
|
||
def success? | ||
false | ||
end | ||
end | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure at this time if I want to assign any attributes, or just use it as a 'pass through' for the adapter to make use of the 'object' (see |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
require 'active_model/serializer/error_serializer' | ||
class ActiveModel::Serializer::ErrorsSerializer | ||
include Enumerable | ||
delegate :each, to: :@serializers | ||
attr_reader :object, :root | ||
|
||
def initialize(resources, options = {}) | ||
@root = options[:root] | ||
@object = resources | ||
@serializers = resources.map do |resource| | ||
serializer_class = options.fetch(:serializer) { ActiveModel::Serializer::ErrorSerializer } | ||
serializer_class.new(resource, options.except(:serializer)) | ||
end | ||
end | ||
|
||
def success? | ||
false | ||
end | ||
|
||
def json_key | ||
nil | ||
end | ||
|
||
protected | ||
|
||
attr_reader :serializers | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Usually, the errors object will be an
ActiveModel::Errors