2017-10-11 10 views
1

Ecto v2.2.6を使用するフェニックス1.3Ectoとのトランザクションで中間挿入の結果を使用

私はブログアプリを持っています。ユーザーが投稿を作成すると、Postテーブルに挿入され、その投稿の結果IDが取得され、Newsfeeditemテーブルに挿入されます。理想的には、私はこれがトランザクションとして起こることを望みます。

(挿入のための私のリターンは、フォーム{:ok, post}でなければなりませんので、私は、アブサンのgraphqlを使用しています)

私はこのようになり、作業機能を持っている:

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に挿入することができます。

私はこの

それをやってのけるする方法任意のアイデアのような何かをしたいですか?

答えて

2

これにはMulti.run/3を使用できます。 Multi.run/3に渡された関数は、これまでの引数の変更を受け取ります。そこから挿入されたpostを抽出し、NewsfeeditemRepo.insertMulti.runに書き出すことができます。この関数は{:ok, _}または{:error, _}を返します。これは正確にはRepo.insertの戻り値なので、関数内で何も処理する必要はありません。

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) 
関連する問題