2017-03-16 70 views
1

我正在使用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: []列表,但我不確定如何做到這一點。

編輯

我要澄清的是,如果我不指定自定義錯誤我仍然與一般錯誤消息得到同樣的錯誤。

+0

的錯誤是Ecto.Changeset,而不是模型的一部分,這樣看起來很奇怪。你能否提供控制器代碼和渲染json的可能的視圖代碼? – Svilen

+0

@Svilen添加了控制器和視圖代碼。我嘗試了幾種將變更集錯誤傳遞給json視圖的方法,但目前爲止沒有喜悅。 – Razzildinho

回答

3

我認爲這是自動完成的,如果您使用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函數定義中。

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 
+0

你知道哪裏定義了'translate_error/1'函數嗎? –

+0

@ Jean-PierreBécotte我已經用函數定義更新了答案。 – Razzildinho

+0

幹得好,@Razzildinho! –