2017-10-11 3 views
1

Ich habe eine Blog-App, in der, wenn jemand einen Beitrag aktualisiert, ein Eintrag in die Newsfeed-Tabelle hinzugefügt wird. Die Post und Newsfeed Schemata sind wie folgt:Probleme beim Aktualisieren eines Datensatzes mit Ecto.Multi

mix phx.new.json Content Post posts title:string content:string 
mix phx.new.json Content Newsfeed newsfeeds message:string 

Hier ist die Wrapper-Funktion:

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 

Und hier ist die Logik im Inhalt Kontext:

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 

Hier ist die update_post Funktion:

def update_post(%Post{} = post, attrs) do 
    post 
    |> Post.changeset(attrs) 
    |> Repo.update() 
    end 

Wenn ich diesen Code ausführen, um das Content-Updates in der Datenbank, aber kein Newsfeed Artikel wird eingefügt, und ich sehe diese Fehlermeldung in der Konsole:

Server: localhost:4000 (http) 
Request: POST /graphiql 
** (exit) an exception was raised: 
    ** (FunctionClauseError) no function clause matching in Ecto.Multi.update/4 

Jede Idee, wie dieses Problem beheben? Ich verwende v2.2.6 und 1.3 mit Absinthe.

+1

Dies könnte zu tun haben, mit Ihnen mit '{: Fehler, _}' statt '{: Fehler, _, _, _}'. Kannst du auch deinen Code für die "update_post" -Methode posten? – Sheharyar

+0

Siehe Update oben –

Antwort

1

Ihr Multi.update/4 Aufruf ist falsch, da ein Changeset erwartet wird. Stattdessen aktualisieren Sie Ihre Post außerhalb der Transaktion und übergeben es das Ergebnis Ihrer Aktualisierung.

Denken Sie daran, der Zweck einer Transaktion besteht im Rollback im Falle eines Fehlers. Das bedeutet, wenn es scheitert, sollten alle Änderungen umgekehrt werden (was in Ihrem Fall nicht passiert).


Ihre update_post Methode löschen und stattdessen übergeben Sie einfach die changeset:

multi = 
    Multi.new 
    |> Multi.update(:post, Post.changeset(post, %{content: content})) 
    |> Multi.insert(:newsfeed, %Newsfeed{message: "post updated"}) 

Auch wenn eine Ecto.Multi Transaktion fehlschlägt, gibt es einen 4-Element-Fehler Tupel, keine reguläres 2-Element eine . So ändern Sie Ihre case Anweisung wie folgt:

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