【问题标题】:Poison unable to encode error message毒药无法编码错误信息
【发布时间】:2017-08-07 18:39:35
【问题描述】:

我使用 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: [] 列表中,但我不确定该怎么做。

编辑

我应该澄清一下,如果我不指定自定义错误,我仍然会收到与通用错误消息相同的错误。

【问题讨论】:

  • 错误是 Ecto.Changeset 的一部分,而不是模型,所以看起来很奇怪。您能否提供呈现 json 的控制器代码和可能的视图代码?
  • @Svilen 添加了控制器和视图代码。我尝试了几种将变更集错误传递给 json 视图的方法,但到目前为止没有任何乐趣。

标签: elixir phoenix-framework elixir-poison


【解决方案1】:

我认为如果您使用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\1 函数定义。这包含在名为 MyApp.ErrorHelpers 的模块中,该模块被导入到 web/my_app.exlib/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

【讨论】:

  • 你知道translate_error/1函数是在哪里定义的吗?
  • @Jean-PierreBécotte 我已经用函数定义更新了答案。
  • 干得好,@Razzildinho!
猜你喜欢
  • 1970-01-01
  • 2017-09-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-27
  • 1970-01-01
  • 2012-05-02
相关资源
最近更新 更多