元组类型的 {:ok, ["Massimo Dutti", "Sneakers laag", "38", "Black", "99.95"]} 未实现协议枚举
protocol Enumerable not implemented for {:ok, ["Massimo Dutti", "Sneakers laag", "38", "Black", "99.95"]} of type Tuple
对于一个学校项目,我们必须在 elixir 中创建一个可以通过上传 csv 文件来创建新产品的网上商店。我们尝试通过遵循 来实现这一点,但我们总是得到一个错误(见标题)
有人可以帮助我们吗?这是我们的代码:
形式
<%= form_for @changeset, @action, [multipart: true], fn f -> %>
<div class="form-group">
<label>File</label>
<%= file_input f, :file, class: "form-control" %>
</div>
<div class="form-group">
<%= submit "Submit", class: "btn btn-primary" %>
</div>
<% end %>
渲染
<%= render "bulkform.html", changeset: @changeset, action: Routes.product_path(@conn, :createBulk) %>
路线
post "/productsBulk", ProductController, :createBulk
架构
schema "products" do
field :color, :string
field :size, :string
field :description, :string
field :price, :decimal
field :title, :string
timestamps()
end
@doc false
def changeset(product, attrs) do
product
|> cast(attrs, [:title, :description, :size, :color, :price, :stock])
|> validate_required([:title, :description, :size, :color, :price, :stock])
|> unique_constraint(:title, name: :unique_products_index, message:
"Title already in use.")
end
控制器
def createBulk(conn, %{"product" => product_params}) do
product_params["file"].path
|> File.stream!()
|> CSV.decode
|> Enum.each(fn(product) -> Product.changeset(%Product{}, %{title: Enum.at(product, 0), description:
Enum.at(product, 1), size: Enum.at(product, 2), color: Enum.at(product, 3), price: Enum.at(product, 4)})
|> Repo.insert() end)
conn
|> put_flash(:info, "Imported")
|> redirect(to: Routes.product_path(conn, :overview))
end
如果您完整地包含错误消息,并且您可以准确地向我们展示错误消息中提到的行,将会更有帮助。
但是,正如 Aleksei 已经指出的那样,我怀疑您的问题是您在应该传递列表时将 元组 传递给 Enum.each/1
。换句话说:
Enum.each({:ok, [1, 2, 3]}, fn x -> IO.puts(x) end)
** (Protocol.UndefinedError) protocol Enumerable not implemented for ...
虽然这很好用:
Enum.each([1, 2, 3], fn x -> IO.puts(x) end)
因此 CSV.decode
的输出不能直接传送到 Enum
函数,因为它 return 是一个元组,但是使用 CSV.decode!
应该 return原始列表和您的代码应该可以工作。
对于一个学校项目,我们必须在 elixir 中创建一个可以通过上传 csv 文件来创建新产品的网上商店。我们尝试通过遵循
有人可以帮助我们吗?这是我们的代码:
形式
<%= form_for @changeset, @action, [multipart: true], fn f -> %>
<div class="form-group">
<label>File</label>
<%= file_input f, :file, class: "form-control" %>
</div>
<div class="form-group">
<%= submit "Submit", class: "btn btn-primary" %>
</div>
<% end %>
渲染
<%= render "bulkform.html", changeset: @changeset, action: Routes.product_path(@conn, :createBulk) %>
路线
post "/productsBulk", ProductController, :createBulk
架构
schema "products" do
field :color, :string
field :size, :string
field :description, :string
field :price, :decimal
field :title, :string
timestamps()
end
@doc false
def changeset(product, attrs) do
product
|> cast(attrs, [:title, :description, :size, :color, :price, :stock])
|> validate_required([:title, :description, :size, :color, :price, :stock])
|> unique_constraint(:title, name: :unique_products_index, message:
"Title already in use.")
end
控制器
def createBulk(conn, %{"product" => product_params}) do
product_params["file"].path
|> File.stream!()
|> CSV.decode
|> Enum.each(fn(product) -> Product.changeset(%Product{}, %{title: Enum.at(product, 0), description:
Enum.at(product, 1), size: Enum.at(product, 2), color: Enum.at(product, 3), price: Enum.at(product, 4)})
|> Repo.insert() end)
conn
|> put_flash(:info, "Imported")
|> redirect(to: Routes.product_path(conn, :overview))
end
如果您完整地包含错误消息,并且您可以准确地向我们展示错误消息中提到的行,将会更有帮助。
但是,正如 Aleksei 已经指出的那样,我怀疑您的问题是您在应该传递列表时将 元组 传递给 Enum.each/1
。换句话说:
Enum.each({:ok, [1, 2, 3]}, fn x -> IO.puts(x) end)
** (Protocol.UndefinedError) protocol Enumerable not implemented for ...
虽然这很好用:
Enum.each([1, 2, 3], fn x -> IO.puts(x) end)
因此 CSV.decode
的输出不能直接传送到 Enum
函数,因为它 return 是一个元组,但是使用 CSV.decode!
应该 return原始列表和您的代码应该可以工作。