我正在尝试合并变更集错误。
我有一个属于用户架构的机构架构。每个字段都需要一些字段,但错误响应如下:
{
"errors": {
"user": {
"password_confirmation": [
"The password confirmation does not match the password."
],
"password": [
"This field is required."
],
"name": [
"This field is required."
]
},
"institution": {
"web_address": [
"is required."
]
},
}
}
如何将这些错误对象组合成一个?
我的插入内容如下:
user_changeset =
User.normal_user_changeset(%User{}, %{
:email => Map.get(attrs, "email"),
:password => Map.get(attrs, "password"),
:password_confirmation => Map.get(attrs, "password_confirmation"),
:name => Map.get(attrs, "name"),
:postcode => Map.get(attrs, "postcode"),
:dob => Map.get(attrs, "dob")
})
institution =
%Institution{}
|> Institution.changeset(%{
:web_address => Map.get(attrs, "web_address"),
:person_responsible => Map.get(attrs, "person_responsible"),
:annual_turnover => Map.get(attrs, "annual_turnover")
})
|> Ecto.Changeset.put_assoc(:user, user_changeset)
|> Repo.insert()
我希望错误响应是:
{
"errors": {
"password_confirmation": [
"The password confirmation does not match the password."
],
"password": [
"This field is required."
],
"name": [
"This field is required."
]
"web_address": [
"is required."
]
}
}
我的后备控制器(默认为此处)中具有此功能:
def call(conn, {:error, %Ecto.Changeset{} = changeset}) do
conn
|> put_status(:unprocessable_entity)
|> render(SfiWeb.ChangesetView, "error.json", changeset: changeset)
end
答案 0 :(得分:1)
您可以获取errors
字段的值,并使用Enum.reduce/3
合并它们:
map = Jason.decode! """
{
"errors": {
"user": {
"password_confirmation": [
"The password confirmation does not match the password."
],
"password": [
"This field is required."
],
"name": [
"This field is required."
]
},
"institution": {
"web_address": [
"is required."
]
}
}
}
"""
Map.update!(map, "errors", fn errors ->
errors |> Map.values() |> Enum.reduce(%{}, &Map.merge/2)
end)
|> IO.inspect
输出:
%{
"errors" => %{
"name" => ["This field is required."],
"password" => ["This field is required."],
"password_confirmation" => ["The password confirmation does not match the password."],
"web_address" => ["is required."]
}
}
答案 1 :(得分:0)
errors
只是%Ecto.Changeset{}
结构中的值之一。
也就是说,总是可以修改%Ecto.Changeset{}
以提供自定义errors
:
def fix_errors(%Ecto.Changeset{errors: errors} = ch) do
%Ecto.Changeset{ch | errors: errors ++ [:my_custom_error]}
end
您需要的只是使用上面的函数重新映射您的输入,并将结果嵌入到变更集链中:
institution =
%Institution{}
|> ...
|> Ecto.Changeset.put_assoc(:user, user_changeset)
|> fix_errors() # see above
|> Repo.insert()
在此之前和之后,无论您是否为errors
提供了有效的Elixir术语,我都可以展示如何自行执行转换。例如:
errors = %{
institution: %{web_address: ["is required"]},
user: %{
name: ["is required."],
password: ["is required."],
password_confirmation: ["no match"]
}
}
可能会展平为:
input
|> Enum.map(fn {_, v} -> v end)
|> Enum.reduce(&Map.merge/2)
#⇒ %{
# name: ["is required."],
# password: ["is required."],
# password_confirmation: ["no match"],
# web_address: ["is required"]
# }