使用 Ecto.Multi 更新记录时遇到问题
Trouble updating a record with Ecto.Multi
我有一个博客应用程序,当有人更新 post 时,它会在新闻源 table 中添加一个条目。 Post
和 Newsfeed
架构如下:
mix phx.new.json Content Post posts title:string content:string
mix phx.new.json Content Newsfeed newsfeeds message:string
这是包装函数:
def updateContent(%{id: id, content: content}, _info) do
post = Repo.get(post, id)
Content.update_content_and_add_to_newsfeed(post, %{id: id, content: content})
end
内容上下文中的逻辑如下:
def update_content_and_add_to_newsfeed(post, %{id: id, content: content}) do
multi =
Multi.new
|> Multi.update(:post, update_post(post, %{content: content}))
|> Multi.insert(:newsfeed, %Newsfeed{message: "post updated"})
case Repo.transaction(multi) do
{:ok, %{post: post}} ->
{:ok, post}
{:error, _} ->
{:error, "Error"}
end
end
这里是 update_post 函数:
def update_post(%Post{} = post, attrs) do
post
|> Post.changeset(attrs)
|> Repo.update()
end
当我 运行 此代码时,数据库中的内容更新,但没有插入新闻源项目,我在控制台中看到此错误消息:
Server: localhost:4000 (http)
Request: POST /graphiql
** (exit) an exception was raised:
** (FunctionClauseError) no function clause matching in Ecto.Multi.update/4
您的 Multi.update/4
调用不正确,因为它需要一个变更集。相反,您在交易之外更新 Post
并将更新结果传递给它。
记住,事务的目的是在出现错误时回滚。这意味着如果它失败了,所有的更改都应该被撤销(这在你的情况下不会发生)。
删除您的 update_post
方法,而只是传递变更集:
multi =
Multi.new
|> Multi.update(:post, Post.changeset(post, %{content: content}))
|> Multi.insert(:newsfeed, %Newsfeed{message: "post updated"})
此外,如果 Ecto.Multi
事务失败,它 returns 是一个 4 元素错误元组,而不是常规的 2 元素错误元组。因此,像这样更改您的 case
语句:
case Repo.transaction(multi) do
{:ok, %{post: post}} ->
{:ok, post}
{:error, _op, _value, _changes} ->
{:error, "Error"}
end
我有一个博客应用程序,当有人更新 post 时,它会在新闻源 table 中添加一个条目。 Post
和 Newsfeed
架构如下:
mix phx.new.json Content Post posts title:string content:string
mix phx.new.json Content Newsfeed newsfeeds message:string
这是包装函数:
def updateContent(%{id: id, content: content}, _info) do
post = Repo.get(post, id)
Content.update_content_and_add_to_newsfeed(post, %{id: id, content: content})
end
内容上下文中的逻辑如下:
def update_content_and_add_to_newsfeed(post, %{id: id, content: content}) do
multi =
Multi.new
|> Multi.update(:post, update_post(post, %{content: content}))
|> Multi.insert(:newsfeed, %Newsfeed{message: "post updated"})
case Repo.transaction(multi) do
{:ok, %{post: post}} ->
{:ok, post}
{:error, _} ->
{:error, "Error"}
end
end
这里是 update_post 函数:
def update_post(%Post{} = post, attrs) do
post
|> Post.changeset(attrs)
|> Repo.update()
end
当我 运行 此代码时,数据库中的内容更新,但没有插入新闻源项目,我在控制台中看到此错误消息:
Server: localhost:4000 (http)
Request: POST /graphiql
** (exit) an exception was raised:
** (FunctionClauseError) no function clause matching in Ecto.Multi.update/4
您的 Multi.update/4
调用不正确,因为它需要一个变更集。相反,您在交易之外更新 Post
并将更新结果传递给它。
记住,事务的目的是在出现错误时回滚。这意味着如果它失败了,所有的更改都应该被撤销(这在你的情况下不会发生)。
删除您的 update_post
方法,而只是传递变更集:
multi =
Multi.new
|> Multi.update(:post, Post.changeset(post, %{content: content}))
|> Multi.insert(:newsfeed, %Newsfeed{message: "post updated"})
此外,如果 Ecto.Multi
事务失败,它 returns 是一个 4 元素错误元组,而不是常规的 2 元素错误元组。因此,像这样更改您的 case
语句:
case Repo.transaction(multi) do
{:ok, %{post: post}} ->
{:ok, post}
{:error, _op, _value, _changes} ->
{:error, "Error"}
end