【问题标题】:Rendering ActiveRecord validation errors with attributes AND full error messages使用属性和完整错误消息呈现 ActiveRecord 验证错误
【发布时间】:2021-08-06 05:03:19
【问题描述】:

这是一个简单的控制器更新操作:

  def update
    note = Note.find(params[:id])

    if note.update(note_params)
      render json: note.to_json
    else
      render json: {errors: note.errors}, status: :unprocessable_entity
    end
  end

这会在表单中呈现错误 {"errors":{"title":["can't be blank"]}}

但我想要它的形式 {"errors":{"title":["Title can't be blank"]}}

只需使用 {errors: note.errors.full_messages}{:errors=>["Title can't be blank"]} 并错过了属性键。

我可以把它变成所需形式的唯一方法似乎有点复杂:

      full_messages_with_keys = note.errors.keys.inject({}) do |hash, key|
        hash[key] = note.errors.full_messages_for(key)
        hash
      end
      render json: {errors: full_messages_with_keys}, status: :unprocessable_entity

这可行,但我必须这样做似乎很奇怪,因为它似乎是在 SPA 前端进行验证的一个非常常见的用例。是否有内置方法/更规范的方式?

【问题讨论】:

  • ActiveModel::Errors 上仅有的两个用于获取消息中的人性化/翻译属性名称的内置选项是 full_messagesfull_messages_for。像你一样使用inject 滚动你自己就是我会做的事情。

标签: ruby-on-rails validation activerecord


【解决方案1】:

您可以使用ActiveModel::Errors#group_by_attribute 获取每个键的错误哈希:

person.errors.group_by_attribute
# => {:name=>[<#ActiveModel::Error>, <#ActiveModel::Error>]}

只需从每个ActiveModel::Error 实例生成完整消息即可:

note.errors
    .group_by_attribute
    .transform_values { |errors| errors.map(&:full_message) }

是否有内置方法/更规范的方式?

不是真的。一个框架不能涵盖所有可能的需求。它提供了根据需要格式化错误所需的工具。

但是,如果您想发疯,可以将此功能推送到模型层、序列化程序甚至猴子补丁上,而不是在您的控制器中重复所有这些。

class ApplicationRecord < ActiveRecord::Base
  def grouped_errors
    errors.group_by_attribute
          .transform_values { |errors| errors.map(&:full_message) }
  end
end

【讨论】:

    猜你喜欢
    • 2013-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多