繁体   English   中英

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

[英]Serializing the errors hash in ActiveModel::Serializer

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

例如,

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

    respond_with book, location: nil
  end
end

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

  if resource.errors.any?
    render json: {:status => 'failed', :errors => resource.errors}
  else
    render json: {:status => 'created', :object => resource}
  end

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

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

ActiveModel::Serializer.serializer_for(book.errors)

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

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

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

示例验证错误

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

{
  "title": [
    "can't be blank"
  ]
}

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

/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

在控制器中使用它

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

结果

{
  "errors": [
    {
      "id": "title",
      "title": "Title can't be blank"
    }
  ]
}

阅读deets的实际帖子。

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

您可以在调用render时使用自定义Serializer,对于这种情况,您可以使用类似的东西

if resource.errors.any?
  render serializer: ErrorSerializer, json: {:status => 'failed', :errors => resource.errors}
else
  render json: {:status => 'created', :object => resource}
end

试一试,告诉我们结果:)

由于响应者如何为错误创建json响应, ErrorsSerializer不起作用:

def json_resource_errors
  { errors: resource.errors }
end

(对于较新的rails,rails <4.2 https://github.com/rails/rails/blob/4-1-stable/actionpack/lib/action_controller/metal/responder.rb#L290 ,响应者已被解压缩到https:// github.com/plataformatec/responders/blob/master/lib/action_controller/responder.rb#L288

处理此问题的一种方法是为响应者覆盖此方法。 将此代码放在配置初始值设定项中:

# config/initializers/action_controller_responder.rb
module ActionController
  class Responder
    def json_resource_errors
      resource.errors
    end
  end
end

然后您的序列化程序将解决资源错误。

resource.errors的类名是ActiveModel::Errors因此您必须将类定义为ActiveModel::ErrorsSerializer

参考: 源代码

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM