2017-10-11 120 views
1

我有一個博客應用程序,當有人更新帖子時,它會將一個條目添加到newsfeed表中。該PostNewsfeed模式如下:使用Ecto.Multi更新記錄時遇到問題

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 

任何想法如何解決這一問題?我正在使用 v2.2.6和 1.3和Absinthe

+1

這可能需要你使用'使用{:錯誤,_}'而不是'{:錯誤,_,_,_}'。你也可以發佈你的'update_post'方法的代碼嗎? – Sheharyar

+0

查看上面的更新 –

回答

1

您的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交易失敗,它返回一個4元素錯誤元組,而不是一個常規的2元一個。因此,改變你的case聲明是這樣的:

case Repo.transaction(multi) do 
    {:ok, %{post: post}} -> 
    {:ok, post} 
    {:error, _op, _value, _changes} -> 
    {:error, "Error"} 
end