create / 2

问题描述

作为我的长生不老药/凤凰学习曲线的一部分,我正在开发一个简单的在线商店。目前,我遇到错误no function clause matching in JordanivaWeb.ProductController.create/2。我尝试使用Arc一次上传多个文件,并且在提交表单时遇到此错误。对于解决此问题的任何帮助或建议,我们将不胜感激。

产品架构:

    schema "products" 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
    |> cast(attrs,[:name,:description,:price,:colour,:product_code,:release_year,:category_id,:subcategory_id,:type_id])
    |> cast_assoc(:items)
    |> cast_assoc(:photos)
    |> validate_required([:name,:type_id])
  end

照片模式

  schema "photos" 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
    |> Map.update(:uuid,Ecto.UUID.generate,fn val -> val || Ecto.UUID.generate end)
    |> cast_attachments(attrs,[:photo])
    |> validate_required([:photo])

产品控制器(新/创建):

  def new(conn,_params) do
    changeset = Product.changeset(%Product{photos: [%Jordaniva.gallery.Photo{}]})
    categories = Repo.all(Category) |> Enum.map(&{&1.name,&1.id})
    subcategories = Repo.all(Subcategory) |> Enum.map(&{&1.name,&1.id})
    render(conn,"new.html",changeset: changeset,categories: categories,subcategories: subcategories)
  end

  def create(conn,%{"product" => product_params}) do

    case Inventory.create_product(product_params) do
      {:ok,product} ->
        conn
        |> put_flash(:info,"Product created successfully.")
        |> redirect(to: Routes.product_path(conn,:show,product))
      {:error,%Ecto.Changeset{} = changeset} ->
        categories = Repo.all(Category) |> Enum.map(&{&1.name,&1.id})
        subcategories = Repo.all(Subcategory) |> Enum.map(&{&1.name,&1.id})
        render(conn,subcategories: subcategories)
    end
  end

请告知是否需要更多代码。预先感谢。

编辑: 错误跟踪

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<:loaded,"types">,id: 3,inserted_at: ~N[2020-08-12 10:46:24],name: "Kids",updated_at: ~N[2020-08-12 10:46:24]},%Jordaniva.Inventory.Type{__Meta__: #Ecto.Schema.Metadata<:loaded,id: 1,name: "Men",id: 2,name: "Women",updated_at: ~N[2020-08-12 10:46:24]}]},before_send: [#Function<0.73641281/1 in Plug.CSRFProtection.call/2>,#Function<2.102658996/1 in Phoenix.Controller.fetch_flash/2>,#Function<0.105793137/1 in Plug.Session.before_send/2>,#Function<0.60895335/1 in Plug.Telemetry.call/2>,#Function<0.33293990/1 in Phoenix.LiveReloader.before_send_inject_reloader/3>],body_params: %{"_csrf_token" => "YiRvKRImFSIaExVsYzpGFixSHgw4DS1K6qWjSGpHmiz4ZB0_F4DmYBYy","photos" => %{"category_id" => "1","colour" => "test11","description" => "test11","name" => "test11","photos" => [%Plug.Upload{content_type: "image/png",filename: "Zrzut ekranu 2020-07-20 o 22.46.06.png",path: "/var/folders/1t/q27498654m376jz6fl02fqd80000gn/T//plug-1597/multipart-1597860468-293284844145788-6"},%Plug.Upload{content_type: "image/png",filename: "Zrzut ekranu 2020-07-20 o 22.46.13.png",path: "/var/folders/1t/q27498654m376jz6fl02fqd80000gn/T//plug-1597/multipart-1597860468-307924305137465-2"},filename: "Zrzut ekranu 2020-07-20 o 22.46.21.png",path: "/var/folders/1t/q27498654m376jz6fl02fqd80000gn/T//plug-1597/multipart-1597860468-503950842927652-2"}],"price" => "11111","product_code" => "test11","release_year" => "2000","subcategory_id" => "1","type_id" => "2"}},cookies: %{"_jordaniva_key" => "SFMyNTY.g3QAAAABbQAAAAtfY3NyZl90b2tlbm0AAAAYVFU4Q0FhZWp3em9YOXh2SWpmWmFhT3Qz.V_FNdlE0nFNXTTd8tO3FXvDggZ0D2el4KMQBf96dszI"},halted: false,host: "localhost",method: "POST",owner: #PID<0.1540.0>,params: %{"_csrf_token" => "YiRvKRImFSIaExVsYzpGFixSHgw4DS1K6qWjSGpHmiz4ZB0_F4DmYBYy",path_info: ["products"],path_params: %{},port: 4000,private: %{JordanivaWeb.Router => {[],%{}},:phoenix_action => :create,:phoenix_controller => JordanivaWeb.ProductController,:phoenix_endpoint => JordanivaWeb.Endpoint,:phoenix_flash => %{},:phoenix_format => "html",:phoenix_layout => {JordanivaWeb.LayoutView,:app},:phoenix_request_logger => {"request_logger","request_logger"},:phoenix_router => JordanivaWeb.Router,:phoenix_view => JordanivaWeb.ProductView,:plug_multipart => :done,:plug_session => %{"_csrf_token" => "TU8CAaejwzoX9xvIjfZaaOt3"},:plug_session_fetch => :done},query_params: %{},query_string: "",remote_ip: {127,1},req_cookies: %{"_jordaniva_key" => "SFMyNTY.g3QAAAABbQAAAAtfY3NyZl90b2tlbm0AAAAYVFU4Q0FhZWp3em9YOXh2SWpmWmFhT3Qz.V_FNdlE0nFNXTTd8tO3FXvDggZ0D2el4KMQBf96dszI"},req_headers: [{"accept","text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"},{"accept-encoding","gzip,deflate"},{"accept-language","pl,en-US;q=0.7,en;q=0.3"},{"connection","keep-alive"},{"content-length","3185491"},{"content-type","multipart/form-data; boundary=---------------------------18456436416963235192732034760"},{"cookie","_jordaniva_key=SFMyNTY.g3QAAAABbQAAAAtfY3NyZl90b2tlbm0AAAAYVFU4Q0FhZWp3em9YOXh2SWpmWmFhT3Qz.V_FNdlE0nFNXTTd8tO3FXvDggZ0D2el4KMQBf96dszI"},{"host","localhost:4000"},{"origin","http://localhost:4000"},{"referer","http://localhost:4000/products/new"},{"upgrade-insecure-requests","1"},{"user-agent","Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:79.0) Gecko/20100101 Firefox/79.0"}],request_path: "/products",resp_body: nil,resp_cookies: %{},resp_headers: [{"cache-control","max-age=0,private,must-revalidate"},{"x-request-id","Fiy9oT4ISHA2dMUAABjm"},{"x-frame-options","SAMEORIGIN"},{"x-xss-protection","1; mode=block"},{"x-content-type-options","nosniff"},{"x-download-options","noopen"},{"x-permitted-cross-domain-policies","none"},{"cross-origin-window-policy","deny"}],scheme: :http,script_name: [],secret_key_base: :...,state: :unset,status: nil}

# 2
%{"_csrf_token" => "YiRvKRImFSIaExVsYzpGFixSHgw4DS1K6qWjSGpHmiz4ZB0_F4DmYBYy","type_id" => "2"}}

编辑2:

错误跟踪:

Protocol.UndefinedError at POST /products
protocol Enumerable not implemented for %Plug.Upload{content_type: "image/png",path: "/var/folders/1t/q27498654m376jz6fl02fqd80000gn/T//plug-1597/multipart-1597863566-633102118642948-6"} 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

新创建的照片控制器:

  def new(conn,_params) do
    changeset = gallery.change_photo(%Photo{})
    render(conn,changeset: changeset)
  end

  def create(conn,%{"product_id" => product_id,"photos" => photo_params}) do
    product = Jordaniva.Inventory.get_product!(product_id)
    with :ok <- gallery.create_photos(photo_params) do
      conn
      |> put_flash(:info,"Upload successful.")
    end
  end

Inventory.ex

  def create_product(attrs \\ %{}) do
    %Product{}
    |> Product.changeset(attrs)
    |> Repo.insert()
  end

gallery.ex

     def create_photos(%Product{} = product,attrs \\ %{}) do
    Enum.each attrs["photos"],fn p ->
      create_photo(product,%{"photo" => p})
    end
  end

gallery.ex中创建照片

 def create_photo(%Product{} = product,attrs \\ %{}) do
    %Photo{}
    |> Photo.changeset(attrs)
    |> Ecto.Changeset.put_assoc(:product,product)
    |> Repo.insert()
  end

解决方法

就像我在评论中建议的那样,发生错误是因为控制器接收到的参数与%{"product" => ...}不匹配,因为从错误消息中可以看出,没有"product"输入第二个参数。

也许您的意思是:

def create(conn,%{"photos" => product_params}) do
  case Inventory.create_product(product_params) do
    {:ok,product} ->
      conn
      |> put_flash(:info,"Product created successfully.")
      |> redirect(to: Routes.product_path(conn,:show,product))
    {:error,%Ecto.Changeset{} = changeset} ->
      categories = Repo.all(Category) |> Enum.map(&{&1.name,&1.id})
      subcategories = Repo.all(Subcategory) |> Enum.map(&{&1.name,&1.id})
      render(conn,"new.html",changeset: changeset,categories: categories,subcategories: subcategories)
  end
end

因为参数中包含"photos",其中包含category_iddescriptionphotos等。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...