这是一个简单的控制器更新操作:
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#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) }
是否有一个内置的方法/更规范的方式?
没有。一个框架不可能涵盖所有可能的需求。它提供了格式化错误所需的工具。
但是,如果你想要疯狂的话,可以将此功能推入模型层,序列化器甚至monkeypatched到ActiveModel::Errors
上,而不是在你的控制器上重复这个功能。
class ApplicationRecord < ActiveRecord::Base
def grouped_errors
errors.group_by_attribute
.transform_values { |errors| errors.map(&:full_message) }
end
end