我有两个型号,产品和图片,我想使用arc包上传产品嵌套表格的多个图像,
这是我的产品型号
defmodule FileUpload.Product do
use FileUpload.Web, :model
schema "products" do
field :name, :string
field :category, :string
has_many :images, FileUpload.Image
timestamps()
end
@doc """
Builds a changeset based on the `struct` and `params`.
"""
def changeset(struct, params \\ %{}) do
struct
|> cast(params, [:name, :category])
|> validate_required([:name, :category])
end
end
我的图像模型
defmodule FileUpload.Image do
use FileUpload.Web, :model
use Arc.Ecto.Schema
schema "images" do
field :image, FileUpload.ImageUploader.Type
belongs_to :product, FileUpload.Product
timestamps()
end
@doc """
Builds a changeset based on the `struct` and `params`.
"""
def changeset(struct, params \\ %{}) do
struct
|> cast(params, [:image])
|> cast_attachments(params, [:image])
end
end
我的图像模型的弧上传器
defmodule FileUpload.ImageUploader do
use Arc.Definition
use Arc.Ecto.Definition
# Include ecto support (requires package arc_ecto installed):
# use Arc.Ecto.Definition
@versions [:original]
# To add a thumbnail version:
@versions [:original, :thumb]
# Whitelist file extensions:
def validate({file, _}) do
~w(.jpg .jpeg .gif .png) |> Enum.member?(Path.extname(file.file_name))
end
# Define a thumbnail transformation:
def transform(:thumb, _) do
{:convert, "-strip -thumbnail 250x250^ -gravity center -extent 250x250 -format png", :png}
end
# Override the storage directory:
def storage_dir(version, {file, scope}) do
"uploads/product/images/#{scope.id}"
end
end
我的ProductController代码用于new和create action
defmodule FileUpload.ProductController do
use FileUpload.Web, :controller
alias FileUpload.Product
def index(conn, _params) do
products = Repo.all(Product)
render(conn, "index.html", products: products)
end
def new(conn, _params) do
changeset = Product.changeset(%Product{images: [%FileUpload.Image{}]})
render(conn, "new.html", changeset: changeset)
end
def create(conn, %{"product" => product_params}) do
changeset = Product.changeset(%Product{}, product_params)
case Repo.insert(changeset) do
{:ok, _product} ->
conn
|> put_flash(:info, "Product created successfully.")
|> redirect(to: product_path(conn, :index))
{:error, changeset} ->
render(conn, "new.html", changeset: changeset)
end
end
end
我的新产品表单
<%= form_for @changeset, @action, [multipart: true], fn f -> %>
<%= if @changeset.action do %>
<div class="alert alert-danger">
<p>Oops, something went wrong! Please check the errors below.</p>
</div>
<% end %>
<div class="form-group">
<%= label f, :name, class: "control-label" %>
<%= text_input f, :name, class: "form-control" %>
<%= error_tag f, :name %>
</div>
<div class="form-group">
<%= label f, :category, class: "control-label" %>
<%= text_input f, :category, class: "form-control" %>
<%= error_tag f, :category %>
</div>
<%= inputs_for f, :images, fn imf -> %>
<div class="form-group">
<%= label imf, :image, class: "control-label" %>
<%= file_input imf, :image, class: "form-control" %>
<%= error_tag imf, :image %>
</div>
<% end %>
<div class="form-group">
<%= submit "Submit", class: "btn btn-primary" %>
</div>
<% end %>
mix.ex应用程序和deps阻止
# Type `mix help compile.app` for more information.
def application do
[mod: {FileUpload, []},
applications: [:phoenix, :phoenix_pubsub, :phoenix_html, :cowboy, :logger, :gettext,
:phoenix_ecto, :postgrex, :arc_ecto, :ex_aws, :hackney, :poison]]
end
# Specifies your project dependencies.
#
# Type `mix help deps` for examples and options.
defp deps do
[{:phoenix, "~> 1.2.1"},
{:phoenix_pubsub, "~> 1.0"},
{:phoenix_ecto, "~> 3.0"},
{:postgrex, ">= 0.0.0"},
{:phoenix_html, "~> 2.6"},
{:phoenix_live_reload, "~> 1.0", only: :dev},
{:gettext, "~> 0.11"},
{:cowboy, "~> 1.0"},
{:arc, "~> 0.6.0-rc3"},
{:arc_ecto, "~> 0.5.0-rc1"},
{:ex_aws, "~> 1.0.0-rc3"},
{:hackney, "~> 1.5"},
{:poison, "~> 2.0"},
{:sweet_xml, "~> 0.5"}
]
end
我可以清楚地看到图像传递给参数
Parameters: %{"_csrf_token" => "BFwuXTIsfSAKZSRvQRUWNDM3HwsEEAAAhof1YzKxl3WVypRsdFhyrA==", "_utf8" => "✓", "product" => %{"category" => "Shrestha", "images" => %{"0" => %{"image" => %Plug.Upload{content_type: "image/jpeg", filename: "levis_jeans_25.jpg", path: "/tmp/plug-1481/multipart-466112-497804-1"}}}, "name" => "Ramita"}}
但只保存产品,而不是图像。我的产品控制器创建操作中是否存在我缺少的内容。我在youtube上观看了一个嵌套的表单视频,在创建操作中它没有任何作用。
请告诉我我遗失的内容和地点。
由于
答案 0 :(得分:1)
您需要在cast_assoc
之后添加对cast
的来电,以便为Image.changeset/2
中的每个图片调用Product
:
defmodule FileUpload.Product do
...
def changeset(struct, params \\ %{}) do
struct
|> cast(params, [:name, :category])
|> cast_assoc(:images)
|> validate_required([:name, :category])
end
end