如何使表格和交易在凤凰+ ecto中发挥出色?

mas*_*lum 2 elixir ecto phoenix-framework

我正在和凤凰+ Ecto一起玩,我偶然发现了一些对我来说不太惯用的东西.

我有一个代表一个表格Invitation.在创建邀请时,我们还需要创建一个User,显然我希望两者都在事务中发生,因此我保持数据一致性.以我的形式,我要求nameemail.

因为我希望Invitation我的视图中的变更集正确地表示错误,所以我最终得到了这个代码...但看起来不太好.

你知道在Phoenix + Ecto有更好的方法吗?

def create(params) do
  Repo.transaction(fn ->
    case Repo.insert(User.email_changeset(%User{}, params)) do
      {:ok, user} ->
        changeset = Invitation.changeset(%Invitation{}, params)
        case Repo.insert(Ecto.Changeset.change(changeset, user_id: user.id)) do
          {:ok, user} ->
            user
          {:error, changeset} ->
            Repo.rollback(changeset)
        end
      {:error, _changeset} ->
        Repo.rollback(%{Ecto.Changeset.add_error(changeset, :email, "Wrong email") | action: :insert})
    end
  end)
end
Run Code Online (Sandbox Code Playgroud)

gco*_*rci 10

您正在寻找with运营商.这种语法的优点在于,如果在任何时候,你没有得到你期望的东西,它会停止命令链并激活你的else块:

Repo.transaction(fn ->
  with {:ok, first_object} <- create_some_object,
       {:ok, second_object} <- create_another(first_object.something)  do
       second_object
  else
    {:error, error_key} ->
      Repo.rollback(error_key)
  end
end)
Run Code Online (Sandbox Code Playgroud)

如果create_some_object没有返回匹配{:ok,first_object}的结构,则永远不会创建second_object.很酷,对吗?