title: no function clause matching in create/2
body: <p>As a part of my elixir/phoenix learning curve, I am developing a simple online shop. At the moment I'm facing the error: <code>no function clause matching in JordanivaWeb.ProductController.create/2</code>. I am trying to upload several files in one go using Arc and when I submit the form I got this error. I would appreciate any help or advice on how to solve this problem.</p>
  <p>Product schema:</p>
  <pre><code>    schema &quot;products&quot; do
      field :colour, :string
      field :description, :string
      field :name, :string
      field :price, :decimal
      field :product_code, :string
      field :release_year, :integer
  
      belongs_to :category, Jordaniva.Categories.Category
      belongs_to :subcategory, Jordaniva.Categories.Subcategory
      belongs_to :type, Jordaniva.Inventory.Type
  
      has_many :items, Jordaniva.Inventory.Item
      has_many :photos, Jordaniva.Gallery.Photo
  
      timestamps()
    end
  
    @doc false
    def changeset(struct, attrs \\ %{}) do
      struct
      |&gt; cast(attrs, [:name, :description, :price, :colour, :product_code, :release_year, :category_id, :subcategory_id, :type_id])
      |&gt; cast_assoc(:items)
      |&gt; cast_assoc(:photos)
      |&gt; validate_required([:name, :description, :price, :colour, :product_code, :release_year, :category_id, :subcategory_id, :type_id])
    end
  </code></pre>
  <p>Photo schema</p>
  <pre><code>  schema &quot;photos&quot; do
      field :photo, Jordaniva.Photo.Type
      field :uuid, :string
  
      belongs_to :product, Jordaniva.Inventory.Product
  
      timestamps()
    end
  
    @doc false
    def changeset(image, attrs) do
      image
      |&gt; Map.update(:uuid, Ecto.UUID.generate, fn val -&gt; val || Ecto.UUID.generate end)
      |&gt; cast_attachments(attrs, [:photo])
      |&gt; validate_required([:photo])
  </code></pre>
  <p>Product controller (new/create):</p>
  <pre><code>  def new(conn, _params) do
      changeset = Product.changeset(%Product{photos: [%Jordaniva.Gallery.Photo{}]})
      categories = Repo.all(Category) |&gt; Enum.map(&amp;{&amp;1.name, &amp;1.id})
      subcategories = Repo.all(Subcategory) |&gt; Enum.map(&amp;{&amp;1.name, &amp;1.id})
      render(conn, &quot;new.html&quot;, changeset: changeset, categories: categories, subcategories: subcategories)
    end
  
    def create(conn, %{&quot;product&quot; =&gt; product_params}) do
  
      case Inventory.create_product(product_params) do
        {:ok, product} -&gt;
          conn
          |&gt; put_flash(:info, &quot;Product created successfully.&quot;)
          |&gt; redirect(to: Routes.product_path(conn, :show, product))
        {:error, %Ecto.Changeset{} = changeset} -&gt;
          categories = Repo.all(Category) |&gt; Enum.map(&amp;{&amp;1.name, &amp;1.id})
          subcategories = Repo.all(Subcategory) |&gt; Enum.map(&amp;{&amp;1.name, &amp;1.id})
          render(conn, &quot;new.html&quot;, changeset: changeset, categories: categories, subcategories: subcategories)
      end
    end
  </code></pre>
  <p>Please, tell if more code is needed. Thanks in advance.</p>
  <p>EDIT:
  Error trace</p>
  <pre><code>The following arguments were given to JordanivaWeb.ProductController.create/2:
  
  # 1
  %Plug.Conn{adapter: {Plug.Cowboy.Conn, :...}, assigns: %{types: [%Jordaniva.Inventory.Type{__meta__: #Ecto.Schema.Metadata&lt;:loaded, &quot;types&quot;&gt;, id: 3, inserted_at: ~N[2020-08-12 10:46:24], name: &quot;Kids&quot;, updated_at: ~N[2020-08-12 10:46:24]}, %Jordaniva.Inventory.Type{__meta__: #Ecto.Schema.Metadata&lt;:loaded, &quot;types&quot;&gt;, id: 1, inserted_at: ~N[2020-08-12 10:46:24], name: &quot;Men&quot;, updated_at: ~N[2020-08-12 10:46:24]}, %Jordaniva.Inventory.Type{__meta__: #Ecto.Schema.Metadata&lt;:loaded, &quot;types&quot;&gt;, id: 2, inserted_at: ~N[2020-08-12 10:46:24], name: &quot;Women&quot;, updated_at: ~N[2020-08-12 10:46:24]}]}, before_send: [#Function&lt;0.73641281/1 in Plug.CSRFProtection.call/2&gt;, #Function&lt;2.102658996/1 in Phoenix.Controller.fetch_flash/2&gt;, #Function&lt;0.105793137/1 in Plug.Session.before_send/2&gt;, #Function&lt;0.60895335/1 in Plug.Telemetry.call/2&gt;, #Function&lt;0.33293990/1 in Phoenix.LiveReloader.before_send_inject_reloader/3&gt;], body_params: %{&quot;_csrf_token&quot; =&gt; &quot;YiRvKRImFSIaExVsYzpGFixSHgw4DS1K6qWjSGpHmiz4ZB0_F4DmYBYy&quot;, &quot;photos&quot; =&gt; %{&quot;category_id&quot; =&gt; &quot;1&quot;, &quot;colour&quot; =&gt; &quot;test11&quot;, &quot;description&quot; =&gt; &quot;test11&quot;, &quot;name&quot; =&gt; &quot;test11&quot;, &quot;photos&quot; =&gt; [%Plug.Upload{content_type: &quot;image/png&quot;, filename: &quot;Zrzut ekranu 2020-07-20 o 22.46.06.png&quot;, path: &quot;/var/folders/1t/q27498654m376jz6fl02fqd80000gn/T//plug-1597/multipart-1597860468-293284844145788-6&quot;}, %Plug.Upload{content_type: &quot;image/png&quot;, filename: &quot;Zrzut ekranu 2020-07-20 o 22.46.13.png&quot;, path: &quot;/var/folders/1t/q27498654m376jz6fl02fqd80000gn/T//plug-1597/multipart-1597860468-307924305137465-2&quot;}, %Plug.Upload{content_type: &quot;image/png&quot;, filename: &quot;Zrzut ekranu 2020-07-20 o 22.46.21.png&quot;, path: &quot;/var/folders/1t/q27498654m376jz6fl02fqd80000gn/T//plug-1597/multipart-1597860468-503950842927652-2&quot;}], &quot;price&quot; =&gt; &quot;11111&quot;, &quot;product_code&quot; =&gt; &quot;test11&quot;, &quot;release_year&quot; =&gt; &quot;2000&quot;, &quot;subcategory_id&quot; =&gt; &quot;1&quot;, &quot;type_id&quot; =&gt; &quot;2&quot;}}, cookies: %{&quot;_jordaniva_key&quot; =&gt; &quot;SFMyNTY.g3QAAAABbQAAAAtfY3NyZl90b2tlbm0AAAAYVFU4Q0FhZWp3em9YOXh2SWpmWmFhT3Qz.V_FNdlE0nFNXTTd8tO3FXvDggZ0D2el4KMQBf96dszI&quot;}, halted: false, host: &quot;localhost&quot;, method: &quot;POST&quot;, owner: #PID&lt;0.1540.0&gt;, params: %{&quot;_csrf_token&quot; =&gt; &quot;YiRvKRImFSIaExVsYzpGFixSHgw4DS1K6qWjSGpHmiz4ZB0_F4DmYBYy&quot;, &quot;photos&quot; =&gt; %{&quot;category_id&quot; =&gt; &quot;1&quot;, &quot;colour&quot; =&gt; &quot;test11&quot;, &quot;description&quot; =&gt; &quot;test11&quot;, &quot;name&quot; =&gt; &quot;test11&quot;, &quot;photos&quot; =&gt; [%Plug.Upload{content_type: &quot;image/png&quot;, filename: &quot;Zrzut ekranu 2020-07-20 o 22.46.06.png&quot;, path: &quot;/var/folders/1t/q27498654m376jz6fl02fqd80000gn/T//plug-1597/multipart-1597860468-293284844145788-6&quot;}, %Plug.Upload{content_type: &quot;image/png&quot;, filename: &quot;Zrzut ekranu 2020-07-20 o 22.46.13.png&quot;, path: &quot;/var/folders/1t/q27498654m376jz6fl02fqd80000gn/T//plug-1597/multipart-1597860468-307924305137465-2&quot;}, %Plug.Upload{content_type: &quot;image/png&quot;, filename: &quot;Zrzut ekranu 2020-07-20 o 22.46.21.png&quot;, path: &quot;/var/folders/1t/q27498654m376jz6fl02fqd80000gn/T//plug-1597/multipart-1597860468-503950842927652-2&quot;}], &quot;price&quot; =&gt; &quot;11111&quot;, &quot;product_code&quot; =&gt; &quot;test11&quot;, &quot;release_year&quot; =&gt; &quot;2000&quot;, &quot;subcategory_id&quot; =&gt; &quot;1&quot;, &quot;type_id&quot; =&gt; &quot;2&quot;}}, path_info: [&quot;products&quot;], path_params: %{}, port: 4000, private: %{JordanivaWeb.Router =&gt; {[], %{}}, :phoenix_action =&gt; :create, :phoenix_controller =&gt; JordanivaWeb.ProductController, :phoenix_endpoint =&gt; JordanivaWeb.Endpoint, :phoenix_flash =&gt; %{}, :phoenix_format =&gt; &quot;html&quot;, :phoenix_layout =&gt; {JordanivaWeb.LayoutView, :app}, :phoenix_request_logger =&gt; {&quot;request_logger&quot;, &quot;request_logger&quot;}, :phoenix_router =&gt; JordanivaWeb.Router, :phoenix_view =&gt; JordanivaWeb.ProductView, :plug_multipart =&gt; :done, :plug_session =&gt; %{&quot;_csrf_token&quot; =&gt; &quot;TU8CAaejwzoX9xvIjfZaaOt3&quot;}, :plug_session_fetch =&gt; :done}, query_params: %{}, query_string: &quot;&quot;, remote_ip: {127, 0, 0, 1}, req_cookies: %{&quot;_jordaniva_key&quot; =&gt; &quot;SFMyNTY.g3QAAAABbQAAAAtfY3NyZl90b2tlbm0AAAAYVFU4Q0FhZWp3em9YOXh2SWpmWmFhT3Qz.V_FNdlE0nFNXTTd8tO3FXvDggZ0D2el4KMQBf96dszI&quot;}, req_headers: [{&quot;accept&quot;, &quot;text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8&quot;}, {&quot;accept-encoding&quot;, &quot;gzip, deflate&quot;}, {&quot;accept-language&quot;, &quot;pl,en-US;q=0.7,en;q=0.3&quot;}, {&quot;connection&quot;, &quot;keep-alive&quot;}, {&quot;content-length&quot;, &quot;3185491&quot;}, {&quot;content-type&quot;, &quot;multipart/form-data; boundary=---------------------------18456436416963235192732034760&quot;}, {&quot;cookie&quot;, &quot;_jordaniva_key=SFMyNTY.g3QAAAABbQAAAAtfY3NyZl90b2tlbm0AAAAYVFU4Q0FhZWp3em9YOXh2SWpmWmFhT3Qz.V_FNdlE0nFNXTTd8tO3FXvDggZ0D2el4KMQBf96dszI&quot;}, {&quot;host&quot;, &quot;localhost:4000&quot;}, {&quot;origin&quot;, &quot;http://localhost:4000&quot;}, {&quot;referer&quot;, &quot;http://localhost:4000/products/new&quot;}, {&quot;upgrade-insecure-requests&quot;, &quot;1&quot;}, {&quot;user-agent&quot;, &quot;Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:79.0) Gecko/20100101 Firefox/79.0&quot;}], request_path: &quot;/products&quot;, resp_body: nil, resp_cookies: %{}, resp_headers: [{&quot;cache-control&quot;, &quot;max-age=0, private, must-revalidate&quot;}, {&quot;x-request-id&quot;, &quot;Fiy9oT4ISHA2dMUAABjm&quot;}, {&quot;x-frame-options&quot;, &quot;SAMEORIGIN&quot;}, {&quot;x-xss-protection&quot;, &quot;1; mode=block&quot;}, {&quot;x-content-type-options&quot;, &quot;nosniff&quot;}, {&quot;x-download-options&quot;, &quot;noopen&quot;}, {&quot;x-permitted-cross-domain-policies&quot;, &quot;none&quot;}, {&quot;cross-origin-window-policy&quot;, &quot;deny&quot;}], scheme: :http, script_name: [], secret_key_base: :..., state: :unset, status: nil}
  
  # 2
  %{&quot;_csrf_token&quot; =&gt; &quot;YiRvKRImFSIaExVsYzpGFixSHgw4DS1K6qWjSGpHmiz4ZB0_F4DmYBYy&quot;, &quot;photos&quot; =&gt; %{&quot;category_id&quot; =&gt; &quot;1&quot;, &quot;colour&quot; =&gt; &quot;test11&quot;, &quot;description&quot; =&gt; &quot;test11&quot;, &quot;name&quot; =&gt; &quot;test11&quot;, &quot;photos&quot; =&gt; [%Plug.Upload{content_type: &quot;image/png&quot;, filename: &quot;Zrzut ekranu 2020-07-20 o 22.46.06.png&quot;, path: &quot;/var/folders/1t/q27498654m376jz6fl02fqd80000gn/T//plug-1597/multipart-1597860468-293284844145788-6&quot;}, %Plug.Upload{content_type: &quot;image/png&quot;, filename: &quot;Zrzut ekranu 2020-07-20 o 22.46.13.png&quot;, path: &quot;/var/folders/1t/q27498654m376jz6fl02fqd80000gn/T//plug-1597/multipart-1597860468-307924305137465-2&quot;}, %Plug.Upload{content_type: &quot;image/png&quot;, filename: &quot;Zrzut ekranu 2020-07-20 o 22.46.21.png&quot;, path: &quot;/var/folders/1t/q27498654m376jz6fl02fqd80000gn/T//plug-1597/multipart-1597860468-503950842927652-2&quot;}], &quot;price&quot; =&gt; &quot;11111&quot;, &quot;product_code&quot; =&gt; &quot;test11&quot;, &quot;release_year&quot; =&gt; &quot;2000&quot;, &quot;subcategory_id&quot; =&gt; &quot;1&quot;, &quot;type_id&quot; =&gt; &quot;2&quot;}}
  </code></pre>
  <p>EDIT 2:</p>
  <p>Error trace:</p>
  <pre><code>Protocol.UndefinedError at POST /products
  protocol Enumerable not implemented for %Plug.Upload{content_type: &quot;image/png&quot;, filename: &quot;Zrzut ekranu 2020-07-20 o 22.46.06.png&quot;, path: &quot;/var/folders/1t/q27498654m376jz6fl02fqd80000gn/T//plug-1597/multipart-1597863566-633102118642948-6&quot;} of type Plug.Upload (a struct). This protocol is implemented for the following type(s): Ecto.Adapters.SQL.Stream, Postgrex.Stream, DBConnection.Stream, DBConnection.PrepareStream, HashSet, Range, Map, Function, List, Stream, Date.Range, HashDict, GenEvent.Stream, MapSet, File.Stream, IO.Stream
  </code></pre>
  <p>Photo controller new/create:</p>
  <pre><code>  def new(conn, _params) do
      changeset = Gallery.change_photo(%Photo{})
      render(conn, &quot;new.html&quot;, changeset: changeset)
    end
  
    def create(conn, %{&quot;product_id&quot; =&gt; product_id, &quot;photos&quot; =&gt; photo_params}) do
      product = Jordaniva.Inventory.get_product!(product_id)
      with :ok &lt;- Gallery.create_photos(photo_params) do
        conn
        |&gt; put_flash(:info, &quot;Upload successful.&quot;)
      end
    end
  </code></pre>
  <p>Inventory.ex</p>
  <pre><code>  def create_product(attrs \\ %{}) do
      %Product{}
      |&gt; Product.changeset(attrs)
      |&gt; Repo.insert()
    end
  </code></pre>
  <p>In gallery.ex</p>
  <pre><code>     def create_photos(%Product{} = product, attrs \\ %{}) do
      Enum.each attrs[&quot;photos&quot;], fn p -&gt;
        create_photo(product, %{&quot;photo&quot; =&gt; p})
      end
    end
  </code></pre>
  <p>create_photo in gallery.ex</p>
  <pre><code> def create_photo(%Product{} = product, attrs \\ %{}) do
      %Photo{}
      |&gt; Photo.changeset(attrs)
      |&gt; Ecto.Changeset.put_assoc(:product, product)
      |&gt; Repo.insert()
    end
  </code></pre>