在ActiveModel :: Serializer中序列化错误哈希

Jac*_*ius 10 serialization json ruby-on-rails active-model-serializers ruby-on-rails-4

我正在使用ActiveModel :: Serializer来自定义我的API的JSON响应.这在大多数情况下都可以正常工作,除非它无法成功保存模型.

例如,

def create
  def create
    book = Book.new(book_params)
    book.save

    respond_with book, location: nil
  end
end
Run Code Online (Sandbox Code Playgroud)

据我了解,respond_with动作基本上会执行看起来像这样的代码(为了生成响应).

  if resource.errors.any?
    render json: {:status => 'failed', :errors => resource.errors}
  else
    render json: {:status => 'created', :object => resource}
  end
Run Code Online (Sandbox Code Playgroud)

这与我所看到的情况相符 - 如果我的模型无法成功保存,我会将错误哈希视为响应.但是,我无法弄清楚如何为错误哈希指定序列化程序.

我尝试定义一个ErrorsSerializer,如果我运行

ActiveModel::Serializer.serializer_for(book.errors)
Run Code Online (Sandbox Code Playgroud)

在控制台中,它似乎找到了我的序列化程序,但它没有得到使用.如何在此方案中自定义JSON响应?

Kin*_*ina 6

我在这篇博文中找到了这个答案......就这样开始......

Rails中错误状态的默认序列化可能不是您想要的应用程序.在这种情况下,了解如何根据需要编写自定义序列化格式是值得的.在我的情况下,我试图匹配JSON API格式的错误.这是一个潜在的实施......

示例验证错误

默认情况下,Rails 4将返回一个类似于此的错误序列化(对于title应始终存在的书籍模型):

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

创建自定义错误序列化程序

/serializers/error_serializer.rb......

module ErrorSerializer

  def self.serialize(errors)
    return if errors.nil?

    json = {}
    new_hash = errors.to_hash(true).map do |k, v|
      v.map do |msg|
        { id: k, title: msg }
      end
    end.flatten
    json[:errors] = new_hash
    json
  end
end
Run Code Online (Sandbox Code Playgroud)

在控制器中使用它

现在include ErrorSerializer在你的控制器中,你可以使用错误哈希来做这样的事情,即render: json: ErrorSerializer.serialize(book.errors)

结果

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

阅读deets的实际帖子.


Mig*_*raz 5

我相信在这种情况下的问题是,对于failed状态,您不会render使用对象来调用它,例如对于created状态。

您可以在调用时使用自定义序列化程序render,在这种情况下,您可以使用类似

if resource.errors.any?
  render serializer: ErrorSerializer, json: {:status => 'failed', :errors => resource.errors}
else
  render json: {:status => 'created', :object => resource}
end
Run Code Online (Sandbox Code Playgroud)

试试看,让我们知道结果:)