2016-12-11 4 views
0

У меня есть две модели, продукта и изображения, и я хочу, чтобы загрузить несколько изображений с продуктом вложенной формы с использованием дугового пакета,феникс используя вложенную форму, используя дугу

Вот моя модель продукта

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 

И моя модель Image

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 код для нового и создать действие

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 и там ничего не делает в создании действия.

Пожалуйста, расскажите мне, что и где я чего-то не хватает.

Благодаря

+1

Попробуйте добавить '|> cast_assoc (: изображения)' после того, как '|> cast (params, [: name,: category])'. – Dogbert

+0

Humm. Спасибо за ответ. Решила мою проблему :). Вы должны были ответить вместо комментариев. – Gagan

ответ

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 
Смежные вопросы