分配 @categories 在 eex 模板中不可用

assign @categories not available in eex template

我有两个模型,产品和类别。我能够 add/edit 具有所选类别的产品,但现在在我设置 Arc 之后,当我尝试添加或编辑产品时,我面临错误:分配 @categories 在 eex 模板中不可用。有谁知道我可能做错了什么或者我的代码中遗漏了什么?我正在使用 Phoenix 1.4。

我的架构:

  schema "products" do
    field :avdate, :date
    field :description, :string
    field :name, :string
    field :price, :float
    field :prodimg, ShopifyWeb.DisplayImage.Type
    field :quantity, :integer
    field :subcategory, :integer
    belongs_to :category, Shopify.Departments.Category
    has_many :comments, Shopify.Reviews.Comment
    timestamps()
  end

  @doc false
  def changeset(product, attrs) do
    product
    |> cast(attrs, [:name, :quantity, :price, :subcategory, :description, :avdate, :category_id])
    |> cast_attachments(attrs, [:prodimg])
    |> validate_required([:name, :quantity, :price, :subcategory, :description, :avdate, :category_id])

  end

  schema "categories" do
    field :name, :string
    field :subcategory, :string
    has_many :products, Shopify.Inventory.Product
    timestamps()
  end

  @doc false
  def changeset(category, attrs) do
    category
    |> cast(attrs, [:name, :subcategory])
    |> validate_required([:name, :subcategory])
  end

New/Edit 在产品控制器中:

  def new(conn, _params) do
    changeset = Inventory.change_product(%Product{})
    categories = Repo.all(Category) |> Enum.map(&{&1.name, &1.id})
    render(conn, "new.html", changeset: changeset, categories: categories)
  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} ->
        render(conn, "new.html", changeset: changeset)
    end
  end

  def show(conn, %{"id" => id}) do
    product = Inventory.get_product!(id)

    comment_changeset = Reviews.change_comment(%Comment{})
    render(conn, "show.html", product: product, comment_changeset: comment_changeset)
  end

  def edit(conn, %{"id" => id}) do
    product = Inventory.get_product!(id)
    changeset = Inventory.change_product(product)
    categories = Repo.all(Category) |> Enum.map(&{&1.name, &1.id})
    render(conn, "edit.html", product: product,  changeset: changeset, categories: categories)
  end

  def update(conn, %{"id" => id, "product" => product_params}) do
    product = Inventory.get_product!(id)

    case Inventory.update_product(product, product_params) do
      {:ok, product} ->
        conn
        |> put_flash(:info, "Product updated successfully.")
        |> redirect(to: Routes.product_path(conn, :show, product))

      {:error, %Ecto.Changeset{} = changeset} ->
        render(conn, "edit.html", product: product, changeset: changeset)
    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 %>

      <%= label f, :name %>
      <%= text_input f, :name %>
      <%= error_tag f, :name %>

      <%= label f, :quantity %>
      <%= number_input f, :quantity %>
      <%= error_tag f, :quantity %>

      <%= label f, :price %>
      <%= number_input f, :price %>
      <%= error_tag f, :price %>

      <div class="form-group">
        <%= select f, :category_id, @categories %>
        <p class="help is-danger"><%= error_tag f, :category %></p>
      </div>


      <%= label f, :subcategory %>
      <%= number_input f, :subcategory %>
      <%= error_tag f, :subcategory %>

      <%= label f, :description %>
      <%= text_input f, :description %>
      <%= error_tag f, :description %>

      <%= label f, :avdate %>
      <%= date_select f, :avdate %>
      <%= error_tag f, :avdate %>

      <div class="form-group">
        <%= label f, :prodimg, class: "control-label" %>
        <%= file_input f, :prodimg, class: "form-control" %>
        <%= error_tag f, :prodimg %>
      </div>


      <div>
        <%= submit "Save" %>
      </div>
    <% end %>

我想当您执行 createupdate 失败时会弹出错误消息?

解决方案:当你呈现错误的表单时,不要忘记获取和分配 categories:

  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}) # <- ADD THIS
        render(conn, "new.html", changeset: changeset, categories: categories)
    end
  end

update 函数也一样。