将ActiveRecord验证错误转换为API耗材错误

Eig*_*ght 4 api rest activerecord ruby-on-rails

我正在Rails 4中编写一个非常标准的CRUD RESTful API.但是我的错误处理却很简单.

想象一下,我有以下型号:

class Book < ActiveRecord::Base
  validates :title, presence: true
end
Run Code Online (Sandbox Code Playgroud)

如果我尝试创建没有标题的图书对象,我将收到以下错误:

{
  "title": [
    "can't be blank"
  ]
}
Run Code Online (Sandbox Code Playgroud)

ActiveRecord验证旨在与Forms一起使用.理想情况下,我希望将每个人类可读验证错误与API使用者可以使用的常量相匹配.所以类似于:

{
  "title": [
    "can't be blank"
  ],
  "error_code": "TITLE_ERROR"
}
Run Code Online (Sandbox Code Playgroud)

这可以用于显示面向用户的错误("标题不能为空"),也可以在其他代码中使用(if response.error_code === TITLE_ERROR...).在Rails中是否有任何工具?

编辑:这是Rails 2天非常相似的问题.

reb*_*tte 11

error_codes.yml定义标准的API错误,包括status_code,title,details和内部code就可以使用,以提供有关您的API文档的错误进一步信息.

这是一个基本的例子:

api:
  invalid_resource:
    code: '1'
    status: '400'
    title: 'Bad Request'

not_found:
    code: '2'
    status: '404'
    title: 'Not Found'
    details: 'Resource not found.'
Run Code Online (Sandbox Code Playgroud)

config/initializers/api_errors.rb上将 YAML文件加载到常量中.

API_ERRORS = YAML.load_file(Rails.root.join('doc','error-codes.yml'))['api']
Run Code Online (Sandbox Code Playgroud)

app/controllers/concerns/error_handling.rb上定义一个可重用的方法来呈现JSON格式的API错误:

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
Run Code Online (Sandbox Code Playgroud)

在您的API基础控制器上包含关注点,因此它可以在从它继承的所有控制器上使用:

include ErrorHandling
Run Code Online (Sandbox Code Playgroud)

然后,您就可以在任何控制器上使用您的方法:

respond_with_error('not_found') # For standard API errors
respond_with_error('invalid_resource', @user) # For invalid resources
Run Code Online (Sandbox Code Playgroud)

例如,在您的用户控制器上,您可能具有以下内容:

def create
  if @user.save(your_api_params)
    # Do whatever your API needs to do
  else
    respond_with_error('invalid_resource', @user)
  end
end
Run Code Online (Sandbox Code Playgroud)

您的API将输出的错误如下所示:

# 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."
}
Run Code Online (Sandbox Code Playgroud)

随着API的增长,您将能够轻松地在YAML文件中添加新的错误代码,并使用此方法避免重复,并使您的API中的错误代码保持一致.


Har*_*tty 5

尝试这个:

book = Book.new(book_params)
if user.save
  render json: book, status: 201
else
  render json: { 
           errors: book.errors,
           error_codes: book.errors.keys.map { |f| f.upcase + "_ERROR" }
         },
         status: 422
end
Run Code Online (Sandbox Code Playgroud)

error_codes返回多个错误代码。