I have a page where admin creates a product along with adding multiple images and videos.
I am uploading multiple images and videos to s3 bucket. So i get 3 struct like below
Product Struct
%{name: "TV", description: "32 inch LED TV", admin_id: "some_binary_id"}
Product Image Struct
[
%{image_name: "image_1.jpg"},
%{image_name: "image_2.jpg"}
]
Product Video Struct
[
%{video_name: "video_1.mp4"},
%{video_name: "video_2.mp4"}
]
I have this 3 schema
Product Schema:
schema "products" do
field :description, :string
field :name, :string
field :admin_id, :binary_id
timestamps()
end
Product Image Schema:
schema "product_images" do
field :image_name, :string
field :product_id, :id
timestamps()
end
Product Video Schema
schema "product_videos" do
field :video_name, :string
field :product_id, :id
timestamps()
end
So first I need to insert product struct. Get the product id and insert in the map of the product image and product video struct and insert in DB
I can do this in 3 queries but I have been looking into Ecto multi, which seems interesting. Can anyone give me insight on how to achieve this in Ecto multi . Your help is greatly appreciated.
Can I do the image and video upload to s3 in the Ecto Multi itself and then insert things in DB?
I checked the Ecto Multi docs but somehow could not able to figure things out from it
I am trying like this but not getting output. Can anyone give me insight on this?
image_params = %{image_name: "test.jpg"}
multi_struct = Multi.new()
|> Multi.insert(:product, Product.changeset(%Product{}, %{name: "TV", description: "Just a test"}))
|> Multi.run(:image, fn %{product: product} ->
Images.changeset(Images, image_params)
|> Ecto.Changeset.put_assoc(product)
|> Repo.insert
end)
What does it mean you’re not getting any output?
The generated Multi struct is inert, you need to pass it to Repo.transaction/1 for it to actually be executed.
image_params = %{image_name: "test.jpg"}
multi_struct = Multi.new()
|> Multi.insert(:product, Product.changeset(%Product{}, %{name: "TV", description: "Just a test"}))
|> Multi.run(:image, fn %{product: product} ->
Images.changeset(Images, image_params)
|> Ecto.Changeset.put_assoc(product)
|> Repo.insert
end)
|> Repo.transaction()
Sorry i mssed to paste it. But i am getting this error
no function clause matching in Ecto.Multi.run/3
The rest of the error and traceback would help 
The second argument to Multi.run (the callback) receives two arguments, not one. The repo and the map of operations.
So it should read:
|> Multi.run(:image, fn _repo, %{product: product} ->
...
end)
2 Likes
This query is good
image_params = %{image_name: "test.jpg"}
multi_struct = Multi.new()
|> Multi.insert(:product, Product.changeset(%Product{}, %{name: "TV", description: "Just a test", admin_id: "773283bd-ee99-48d8-bc47-f5b62321dd6d"}))
|> Multi.run(:image, fn _repo, %{product: product} ->
Images.changeset(%Images{}, image_params)
|> Ecto.Changeset.put_assoc(product)
|> Repo.insert
end)
|> Repo.transaction
But i am getting " function Ecto.Changeset.put_assoc/2 is undefined or private" Any idea?
Fixed thanks
|> Ecto.Changeset.put_assoc(:products, product)
image_params = %{image_name: "test.jpg"}
multi_struct = Multi.new()
|> Multi.insert(:product, Product.changeset(%Product{}, %{name: "TV", description: "Just a test", admin_id: "773283bd-ee99-48d8-bc47-f5b62321dd6d"}))
|> Multi.run(:image, fn _repo, %{product: product} ->
Images.changeset(%Images{}, image_params)
|> Ecto.Changeset.put_assoc(:products, product)
|> Repo.insert # returns a {:ok, user} or {:error, changeset}
end)
|> Repo.transaction