在与 Ecto 的交易中使用中间插入的结果
Using result of intermediate insert in transaction with Ecto
使用 Ecto v2.2.6,Phoenix 1.3
我有一个博客应用程序。当用户生成 Post 时,它会插入 Post
table,然后它会得到 post 的结果 ID,并将其插入 Newsfeeditem
table。理想情况下,我希望这作为交易发生。
(我使用的是 Absinthe graphql,所以我的 return 插入格式必须是 {:ok, post}
)
我有一个看起来像这样的工作函数:
def create_post_add_newsfeed(%{
title: title,
content: content,
user_id: user_id
}) do
case Repo.insert!(%Post{title: title, content: content, user_id: user_id}) do
post ->
case Repo.insert!(%Newsfeeditem{type: "user_creates_post", user_id: user_id, post_id: post.id}) do
newsfeeditem ->
{:ok, post}
_ ->
{:error, "Post not recorded in newsfeed"}
end
_ ->
{:error, "Post not inserted"}
end
end
此代码不是事务,并且散发出回调的臭味。 Ecto.Multi 似乎是一个更适合在这里使用的工具,但我不知道如何获得 Post
插入的结果,以便我可以将其插入 Newsfeed
.
我想做这样的事情
def create_post_add_newsfeed(%{
title: title,
content: content,
user_id: user_id
}) do
multi =
Multi.new
|> Multi.insert(:post, %Post{title: title, content: content, user_id: user_id})
|> # Some intermediate step where I get the 'post' from the line above
|> Multi.insert(:newsfeeditem, %Newsfeeditem{type: "user_creates_post", user_id: users_id, post_id: post.id})
case Repo.transaction(multi) do
{:ok, %{post: post}} ->
{:ok, post}
{:error, _} ->
{:error, "Error"}
end
end
知道如何做到这一点吗?
您可以为此使用 Multi.run/3
。传递给 Multi.run/3
的函数将接收到参数为止的更改。您可以从中提取插入的 post
并为 Multi.run
中的 Newsfeeditem
发出 Repo.insert
。该函数应该 return {:ok, _}
或 {:error, _}
这正是 Repo.insert
returns 所以您不需要在函数内部做任何事情。
Multi.new
|> Multi.insert(:post, %Post{title: title, content: content, user_id: user_id})
|> Multi.run(:newsfeeditem, fn %{post: post} ->
Repo.insert(%Newsfeeditem{type: "user_creates_post", user_id: users_id, post_id: post.id})
end)
使用 Ecto v2.2.6,Phoenix 1.3
我有一个博客应用程序。当用户生成 Post 时,它会插入 Post
table,然后它会得到 post 的结果 ID,并将其插入 Newsfeeditem
table。理想情况下,我希望这作为交易发生。
(我使用的是 Absinthe graphql,所以我的 return 插入格式必须是 {:ok, post}
)
我有一个看起来像这样的工作函数:
def create_post_add_newsfeed(%{
title: title,
content: content,
user_id: user_id
}) do
case Repo.insert!(%Post{title: title, content: content, user_id: user_id}) do
post ->
case Repo.insert!(%Newsfeeditem{type: "user_creates_post", user_id: user_id, post_id: post.id}) do
newsfeeditem ->
{:ok, post}
_ ->
{:error, "Post not recorded in newsfeed"}
end
_ ->
{:error, "Post not inserted"}
end
end
此代码不是事务,并且散发出回调的臭味。 Ecto.Multi 似乎是一个更适合在这里使用的工具,但我不知道如何获得 Post
插入的结果,以便我可以将其插入 Newsfeed
.
我想做这样的事情
def create_post_add_newsfeed(%{
title: title,
content: content,
user_id: user_id
}) do
multi =
Multi.new
|> Multi.insert(:post, %Post{title: title, content: content, user_id: user_id})
|> # Some intermediate step where I get the 'post' from the line above
|> Multi.insert(:newsfeeditem, %Newsfeeditem{type: "user_creates_post", user_id: users_id, post_id: post.id})
case Repo.transaction(multi) do
{:ok, %{post: post}} ->
{:ok, post}
{:error, _} ->
{:error, "Error"}
end
end
知道如何做到这一点吗?
您可以为此使用 Multi.run/3
。传递给 Multi.run/3
的函数将接收到参数为止的更改。您可以从中提取插入的 post
并为 Multi.run
中的 Newsfeeditem
发出 Repo.insert
。该函数应该 return {:ok, _}
或 {:error, _}
这正是 Repo.insert
returns 所以您不需要在函数内部做任何事情。
Multi.new
|> Multi.insert(:post, %Post{title: title, content: content, user_id: user_id})
|> Multi.run(:newsfeeditem, fn %{post: post} ->
Repo.insert(%Newsfeeditem{type: "user_creates_post", user_id: users_id, post_id: post.id})
end)