Poison 无法编码错误消息
Poison unable to encode error message
我正在使用 phoenix 作为 JSON API。我的一个模型如下所示,除非 unique_constraint 检查失败,否则效果很好。当发生这种情况时,我收到以下错误:
(Poison.EncodeError) unable to encode value: {"Email address is already registered", []}
型号:
defmodule MyApp.Registration do
use MyApp.Web, :model
@derive {Poison.Encoder, only: [:name, :email, :category]}
schema "registrations" do
field :name, :string
field :category, :string
field :email, :string
timestamps
end
def changeset(model, params \ :empty) do
model
|> cast(params, ~w(name email category), [])
|> validate_length(:name, min: 1, max: 240)
|> unique_constraint(:email, message: "Email address is already registered")
end
end
控制器:
def create(conn, registration_params) do
changeset = Registration.changeset(%Registration{}, registration_params)
case Repo.insert(changeset) do
{:ok, _registration} ->
# Success
{:error, error} ->
conn
|> put_status(:unprocessable_entity)
|> render(MyApp.ErrorView, "generic.json", error: error)
end
end
查看:
def render("generic.json", error) do
error
end
我想我可能需要以某种方式将错误消息添加到 Poison.Encoder, only: []
列表中,但我不确定该怎么做。
编辑
我应该澄清一下,如果我不指定自定义错误,我仍然会收到相同的错误消息和一般错误消息。
我认为如果您使用 mix phoenix.gen.json
,这会自动完成,但需要将变更集错误转换为 json。
查看:
def translate_errors(changeset) do
Ecto.Changeset.traverse_errors(changeset, &translate_error/1)
end
def render("error.json", %{changeset: changeset}) do
# When encoded, the changeset returns its errors
# as a JSON object. So we just pass it forward.
%{errors: translate_errors(changeset)}
end
控制器:
def create(conn, registration_params) do
changeset = Registration.changeset(%Registration{}, registration_params)
case Repo.insert(changeset) do
{:ok, _registration} ->
# Success
{:error, changeset} ->
conn
|> put_status(:unprocessable_entity)
|> render(MyApp.ErrorView, "error.json", changeset: changeset)
end
end
编辑
添加translate_error
函数定义。这包含在一个名为 MyApp.ErrorHelpers
的模块中,该模块被导入到 web/my_app.ex
或 lib/my_app_web.ex
中的 view
函数定义中,具体取决于您的 phoenix 版本。
lib/my_app_web/views/error_helpers.ex
:
defmodule MyAppWeb.ErrorHelpers do
def translate_error({msg, opts}) do
if count = opts[:count] do
Gettext.dngettext(MyAppWeb.Gettext, "errors", msg, msg, count, opts)
else
Gettext.dgettext(MyAppWeb.Gettext, "errors", msg, opts)
end
end
end
我正在使用 phoenix 作为 JSON API。我的一个模型如下所示,除非 unique_constraint 检查失败,否则效果很好。当发生这种情况时,我收到以下错误:
(Poison.EncodeError) unable to encode value: {"Email address is already registered", []}
型号:
defmodule MyApp.Registration do
use MyApp.Web, :model
@derive {Poison.Encoder, only: [:name, :email, :category]}
schema "registrations" do
field :name, :string
field :category, :string
field :email, :string
timestamps
end
def changeset(model, params \ :empty) do
model
|> cast(params, ~w(name email category), [])
|> validate_length(:name, min: 1, max: 240)
|> unique_constraint(:email, message: "Email address is already registered")
end
end
控制器:
def create(conn, registration_params) do
changeset = Registration.changeset(%Registration{}, registration_params)
case Repo.insert(changeset) do
{:ok, _registration} ->
# Success
{:error, error} ->
conn
|> put_status(:unprocessable_entity)
|> render(MyApp.ErrorView, "generic.json", error: error)
end
end
查看:
def render("generic.json", error) do
error
end
我想我可能需要以某种方式将错误消息添加到 Poison.Encoder, only: []
列表中,但我不确定该怎么做。
编辑
我应该澄清一下,如果我不指定自定义错误,我仍然会收到相同的错误消息和一般错误消息。
我认为如果您使用 mix phoenix.gen.json
,这会自动完成,但需要将变更集错误转换为 json。
查看:
def translate_errors(changeset) do
Ecto.Changeset.traverse_errors(changeset, &translate_error/1)
end
def render("error.json", %{changeset: changeset}) do
# When encoded, the changeset returns its errors
# as a JSON object. So we just pass it forward.
%{errors: translate_errors(changeset)}
end
控制器:
def create(conn, registration_params) do
changeset = Registration.changeset(%Registration{}, registration_params)
case Repo.insert(changeset) do
{:ok, _registration} ->
# Success
{:error, changeset} ->
conn
|> put_status(:unprocessable_entity)
|> render(MyApp.ErrorView, "error.json", changeset: changeset)
end
end
编辑
添加translate_error
函数定义。这包含在一个名为 MyApp.ErrorHelpers
的模块中,该模块被导入到 web/my_app.ex
或 lib/my_app_web.ex
中的 view
函数定义中,具体取决于您的 phoenix 版本。
lib/my_app_web/views/error_helpers.ex
:
defmodule MyAppWeb.ErrorHelpers do
def translate_error({msg, opts}) do
if count = opts[:count] do
Gettext.dngettext(MyAppWeb.Gettext, "errors", msg, msg, count, opts)
else
Gettext.dgettext(MyAppWeb.Gettext, "errors", msg, opts)
end
end
end