将ActiveRecord验证错误转换为API消耗错误 [英] Transforming ActiveRecord validation errors into API consumable errors
问题描述
我正在用Rails 4编写一个非常标准的CRUD RESTful API。
I'm writing a pretty standard CRUD RESTful API in Rails 4. I'm coming up short on error handling though.
想象一下我有以下模型:
Imagine I have the following model:
class Book < ActiveRecord::Base
validates :title, presence: true
end
如果我尝试创建没有标题的书本对象,但会出现以下错误:
If I try to create a book object without a title I'll get the following error:
{
"title": [
"can't be blank"
]
}
ActiveRecord验证旨在与Forms一起使用。理想情况下,我想用API使用者可以使用的常量来匹配每个人类可读的验证错误。就像这样:
ActiveRecord validations are designed to be used with Forms. Ideally I'd like to match up each human readable validation error with a constant that can be used by an API consumer. So something like:
{
"title": [
"can't be blank"
],
"error_code": "TITLE_ERROR"
}
这既可以用于显示用户面临的错误(标题不能为空 ),也可以在其他代码中使用( if response.error_code === TITLE_ERROR
...)。在Rails中有用于此的任何工具吗?
This can be both used to display user facing errors ("title can't be blank") and can be used within other code (if response.error_code === TITLE_ERROR
...). Is there any tooling for this in Rails?
编辑:这是来自Rails 2天的非常类似的问题。
推荐答案
在 error_codes.yml 上,定义您的标准API错误,包括 status_code
, title
,详细信息
和内部代码
,然后可以使用它们在API文档中提供有关错误的更多信息。
On error_codes.yml define your standard API errors, including status_code
, title
, details
and an internal code
you can then use to provide further info about the error on your API documentation.
这是一个基本示例:
api:
invalid_resource:
code: '1'
status: '400'
title: 'Bad Request'
not_found:
code: '2'
status: '404'
title: 'Not Found'
details: 'Resource not found.'
在 config / initializers / api_errors.rb 上,将该YAML文件加载到常量中。
On config/initializers/api_errors.rb load that YAML file into a constant.
API_ERRORS = YAML.load_file(Rails.root.join('doc','error-codes.yml'))['api']
在 app / controllers / concerns / error_handling.rb 上定义一种可重用的方法,以JSON格式呈现API错误:
On app/controllers/concerns/error_handling.rb define a reusable method to render your API errors in JSON format:
module ErrorHandling
def respond_with_error(error, invalid_resource = nil)
error = API_ERRORS[error]
error['details'] = invalid_resource.errors.full_messages if invalid_resource
render json: error, status: error['status']
end
end
在您的API基本控制器上包括该关注点,因此它在从其继承的所有控制器上都可用:
On your API base controller include the concern so it's available on all the controllers which inherit from it:
include ErrorHandling
然后您将能够在这些控制器中的任何一个上使用您的方法:
You will then be able to use your method on any of those controllers:
respond_with_error('not_found') # For standard API errors
respond_with_error('invalid_resource', @user) # For invalid resources
例如,在用户控制器上,您可能具有以下内容:
For example on your users controller you may have the following:
def create
if @user.save(your_api_params)
# Do whatever your API needs to do
else
respond_with_error('invalid_resource', @user)
end
end
您的API将输出的错误如下所示:
The errors your API will output will look like this:
# For invalid resources
{
"code": "1",
"status": "400",
"title": "Bad Request",
"details": [
"Email format is incorrect"
]
}
# For standard API errors
{
"code": "2",
"status": "404",
"title": "Not Found",
"details": "Route not found."
}
随着API的增长,您将能够轻松添加新的错误代码在您的YAML文件上,并将其与该方法一起使用,以避免重复,并使您的错误代码在整个API中保持一致。
As your API grows, you'll be able to easily add new error codes on your YAML file and use them with this method avoiding duplication and making your error codes consistent across your API.
这篇关于将ActiveRecord验证错误转换为API消耗错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!