Elixir 如何使表单和交易在凤凰城发挥良好作用+;外星人?
我正在玩Phoenix+Ecto,我偶然发现了一些我觉得不习惯的东西 我有一个表示邀请的表单。在创建邀请时,我们还需要创建一个Elixir 如何使表单和交易在凤凰城发挥良好作用+;外星人?,elixir,phoenix-framework,ecto,Elixir,Phoenix Framework,Ecto,我正在玩Phoenix+Ecto,我偶然发现了一些我觉得不习惯的东西 我有一个表示邀请的表单。在创建邀请时,我们还需要创建一个用户,显然我希望这两种情况都发生在一个事务中,以便保持数据的一致性。在我的表格中,我要求姓名和电子邮件 由于我希望视图中的邀请变更集能够正确表示错误,因此我最终得到了以下代码。。。但是看起来不太好 你知道一个更好的方法在凤凰+星上做到这一点吗 def创建(参数)do 回购交易(fn-> case Repo.insert(User.email_changeset(%User
用户
,显然我希望这两种情况都发生在一个事务中,以便保持数据的一致性。在我的表格中,我要求姓名
和电子邮件
由于我希望视图中的邀请
变更集能够正确表示错误,因此我最终得到了以下代码。。。但是看起来不太好
你知道一个更好的方法在凤凰+星上做到这一点吗
def创建(参数)do
回购交易(fn->
case Repo.insert(User.email_changeset(%User{},params))do
{:好的,用户}->
变更集=邀请。变更集(%Invitation{},params)
案例报告插入(外部变更集变更(变更集,用户\u id:user.id))do
{:好的,用户}->
用户
{:错误,变更集}->
回购回滚(变更集)
结束
{:错误,_changeset}->
Repo.rollback(%%{exto.Changeset.add_error(Changeset,:email,“错误的email”)| action::insert})
结束
(完)
结束
您可以尝试使用exto.Multi
。以下是一个示例:
defmodule Service do
alias Ecto.Multi
import Ecto
def insert_changeset(params) do
Multi.new
|> Multi.insert(:user, User.email_changeset(%User{}, params))
|> Multi.insert(:invitation, Invitation.changeset(%Invitation{}, params))
end
end
以及您的创建功能:
def create(params) do
Service.insert_changeset(params)
|> Repo.transaction
end
或者,您可以通过模式匹配使代码更漂亮
def create(params) do
Repo.transaction(fn ->
changeset = User.email_changeset(%User{}, params)
changeset
|> Repo.insert
|> invitation_insert(params)
end)
end
defp invitation_insert({:error, changeset}, _params), do: Repo.rollback(changeset)
defp invitation_insert({:ok, _}, params) do
Invitation.changeset(%Invitation{}, params)
|> Repo.insert
|> do_invitation_insert
end
defp do_invitation_insert({:ok, user}), do: user
defp do_invitation_insert({:error, changeset}), do: Repo.rollback(changeset)
您正在使用运算符查找
。这种语法的妙处在于,如果在任何时候,您没有得到预期的结果,它会停止命令链并触发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)
回购交易(fn->
使用{:ok,first_object}时,我想使用Multi
,但在我的例子中,我需要首先创建user
,因为我需要user\u id
作为我的邀请。看起来Multi
是用于“并行”操作的。模式匹配版本看起来确实更好!是否defp做邀请插入({:error,changeset}),do:Repo.rollback(changeset)
也回滚User
?@Omin是的,它仍然在同一事务中。但是,如何将错误从EXTO.Multi返回到表单?