elixir

时间:2017-06-12 08:59:50

标签: elixir phoenix-framework

我正在使用简单的凤凰灵药应用程序。在这个应用程序中,我正在尝试公开一个rest api来保存和检索数据。

在我的情况下,如果主键(电子邮件地址)是重复的,我的应用程序会抛出错误。 我需要知道处理这个错误的最佳方法;无论是试用还是其他更好的解决方案。

这是我的数据保存方法

def post(conn, %{"stooge" => stooge, "name" => name, "email" => email , "password" => password})do
    respond = Repo.insert!(%ApiDb.User{name: name, email: email, stooge: stooge, password: password})
    json conn, respond
  end

样本有效载荷

{
    "stooge": "moe",
    "name": "Joe",
    "email": "p31111ww11eee32111111134@dmain.com",
    "password":"asdasd"
}

模型/ user.ex

defmodule ApiDb.User do
  use ApiDb.Web, :model
  schema "users" do
    field :password, :string
    field :name, :string
    field :email, :string
    field :stooge, :string
    timestamps()
  end

   @doc """
  Builds a changeset based on the `struct` and `params`.
  """
  def changeset(struct, params \\ %{}) do
    struct
    |> cast(params, [:name, :email, :password, :stooge])
    |> validate_required([:name, :email, :password])
    |> validate_format(:email, ~r/@/)
  end
end

错误 enter image description here

我尝试过try-catch块,但没有运气

try do
    respond = Repo.insert!(%ApiDb.User{name: name, email: email, stooge: stooge, password: password})
    json conn, respond
rescue 
  e in Ecto.ConstraintError -> IO.puts("An error occurred: ")
end

3 个答案:

答案 0 :(得分:4)

调用ApiDbUser.changeset函数,然后使用changeset调用Repo.insert。它将返回元组:ok或:error

def post(conn, params) do
  changeset = ApiDb.User.changeset(%ApiDb.User{}, params)
  case Repo.insert(changeset) do
    {:ok, user} -> 
       # create a render("user.json", params) function in your UserView
       render conn, "user.json", user: user
    {:error, changeset} 
      # create a render("error.json", params) function in your UserView
      render conn, "error.json", changeset: changeset
  end
end

答案 1 :(得分:2)

Phoenix 1.3发布后,还有另一种方式:用户action_fallback 以下是docs

中的示例
defmodule MyController do
  use Phoenix.Controller

  action_fallback MyFallbackController

  def show(conn, %{"id" => id}, current_user) do
    with {:ok, post} <- Blog.fetch_post(id),
         :ok <- Authorizer.authorize(current_user, :view, post) do

      render(conn, "show.json", post: post)
    end
  end
end

它允许将错误处理移至回退控制器并在整个应用程序中重复使用:

defmodule MyFallbackController do
  use Phoenix.Controller

  def call(conn, {:error, :not_found}) do
    conn
    |> put_status(:not_found)
    |> render(MyErrorView, :"404")
  end

  def call(conn, {:error, :unauthorized}) do
    conn
    |> put_status(403)
    |> render(MyErrorView, :"403")
  end
end

答案 2 :(得分:0)

找到了很好的方法来做到这一点

 def post(conn, %{"stooge" => stooge, "name" => name, "email" => email , "password" => password})do
    try do
        respond = Repo.insert!(%ApiDb.User{name: name, email: email, stooge: stooge, password: password})
        json conn, respond
    rescue 
      e in Ecto.ConstraintError ->  json conn, (%{"status" => false, "message" => e.message})
    end
  end