You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
First, extract the `ActiveResource::ErrorsParser` class along with the
internal `ActiveResource::ActiveModelErrorsParser` class (that inherits
from `ActiveResource::ErrorsParser`). Configure a `errors_parser`
resource class attribute to control how errors are extracted from
decoded payloads.
The `errors_parser` pattern and the `ErrorsParser` class are directly
inspired by the `collection_parser` and `ActiveResource::Collection`
class.
ActiveResource::ErrorsParser
---
`ActiveResource::ErrorsParser` is a wrapper to handle parsing responses in
response to invalid requests that do not directly map to Active Model
error conventions.
You can define a custom class that inherits from
`ActiveResource::ErrorsParser` in order to to set the elements instance.
The initialize method will receive the `ActiveResource::Formats` parsed
result and should set `@messages`.
Consider a `POST /posts.json` request that results in a `422
Unprocessable Content` response with the following `application/json`
body:
```json
{
"error": true,
"messages": ["Something went wrong", "Title can't be blank"]
}
```
A Post class can be setup to handle it with:
```ruby
class Post < ActiveResource::Base
self.errors_parser = PostErrorsParser
end
```
A custom `ActiveResource::ErrorsParser` instance's `messages` method
should return a mapping of attribute names (or `"base"`) to arrays of
error message strings:
```ruby
class PostErrorsParser < ActiveResource::ErrorsParser
def initialize(parsed)
@messages = Hash.new { |hash, attr_name| hash[attr_name] = [] }
parsed["messages"].each do |message|
if message.starts_with?("Title")
@messages["title"] << message
else
@messages["base"] << message
end
end
end
end
```
When the `POST /posts.json` request is submitted by calling `save`, the
errors are parsed from the body and assigned to the Post instance's
`errors` object:
```ruby
post = Post.new(title: "")
post.save # => false
post.valid? # => false
post.errors.messages_for(:base) # => ["Something went wrong"]
post.errors.messages_for(:title) # => ["Title can't be blank"]
```
If the custom `ActiveResource::ErrorsParser` instance's `messages`
method returns an array of error message strings, Active Resource will
try to infer the attribute name based on the contents of the error
message string. If an error starts with a known attribute name, Active
Resource will add the message to that attribute's error messages. If a
known attribute name cannot be inferred, the error messages will be
added to the `:base` errors:
```ruby
class PostErrorsParser < ActiveResource::ErrorsParser
def initialize(parsed)
@messages = parsed["messages"]
end
end
```
Changes to ActiveResource::Formats::JsonFormat and ActiveResource::Formats::XmlFormat
---
This commit changes the `ActiveResource::Errors#from_xml` and
`ActiveResource::Errors#from_json` methods to be implemented in terms of
a new `#from_body` method. The `#from_body` method is flexible enough to
support any application-side custom formats, while internally flexible
enough to rely on the built-in JSON and XML formats.
mock.post"/people.xml",{},%q(<?xml version="1.0" encoding="UTF-8"?><error><messages>Age can't be blank</messages><messages>Name can't be blank</messages></error>),422,{}
160
+
mock.post"/people.json",{},%q({"error":{"messages":["Age can't be blank", "Name can't be blank"]}}),422,{}
0 commit comments