ruby-on-rails 呈现具有属性和完整错误消息的ActiveRecord验证错误

pn9klfpd  于 5个月前  发布在  Ruby
关注(0)|答案(2)|浏览(66)

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

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前端进行验证的一个非常常见的用例。

a0zr77ik

a0zr77ik1#

您可以使用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) }


是否有一个内置的方法/更规范的方式?
不完全是。一个框架不可能涵盖所有可能的需求。它提供了所需的工具来格式化错误。
然而,如果你想疯狂的话,这个功能可以被推到模型层、序列化器甚至是ActiveModel::Errors上的monopoly上,而不是在你的控制器上重复这个功能。

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

xmd2e60i

xmd2e60i2#

您可以向to_hashto_json传递一个附加参数,以生成包含属性名称的消息:
person.errors.to_hash(true)

person.errors.to_json(full_messsages: true)
都将返回{"title":["Title can't be blank"]}

相关问题