Error when edit Product Schema

Hi for all, i have this error:

list in Phoenix.Html and templates may only contain integers representing bytes , binaries, or other list, got invalid entry: #Ecto.Changeset <action: :replace, changes: %{}, errors [], data: #Shop.Catalog.Tag<>, valid?: true 

when edit the Product Schema , after add the :tags relation , when create the product, everything ok, the problem is when edit.

Here my Product Schema:

defmodule Shop.Catalog.Product do
  use Ecto.Schema
  import Ecto.Changeset
  
  alias Shop.Catalog.{Product, Variant, ProductOptionType, ProductCategory, Tag, ProductTag}
  alias Shop.Validations.Date
  alias Shop.Repo


  schema "products" do
    field :name, :string
    field :slug, :string
    field :description, :string
    field :available_on, Ecto.Date
    field :discontinue_on, Ecto.Date
    field :meta_description, :string
    field :meta_keywords, :string
    field :short_description, :string
	
    has_one :master, Variant, on_delete: :nilify_all 
    has_many :variants, Variant, on_delete: :nilify_all

    has_many :product_option_types, ProductOptionType, on_delete: :nilify_all
    has_many :option_types, through: [:product_option_types, :option_type]

    has_many :product_categories, ProductCategory, on_delete: :nilify_all
    has_many :categories, through: [:product_categories, :category]
	
    many_to_many :tags, Tag, join_through: ProductTag, on_replace: :delete

    timestamps()
 end

  @doc false
  def changeset(%Product{} = product, attrs) do
    product
    |> cast(attrs, [:name, :slug, :description, :available_on, :discontinue_on, :meta_description, :meta_keywords, :short_description])
    |> validate_required([:name, :description, :available_on, :meta_description, :meta_keywords, :short_description])
	|> Date.validate_not_past_date(:available_on)
	|> Shop.Slug.generate_slug()
    |> cast_assoc(:product_option_types, with: &ProductOptionType.from_product_changeset/2)
    |> cast_assoc(:product_categories, with: &ProductCategory.from_product_changeset/2)
	|> put_assoc(:tags, parse_tags(attrs))
    |> unique_constraint(:slug)
  end
  
  def create_changeset(%Product{} = product, attrs \\ %{}) do
    changeset(product, attrs)
    |> cast_assoc(:master, required: true, with: &Variant.create_master_changeset/2)
  end

   def update_changeset(%Product{} = product, attrs \\ %{}) do
    changeset(product, attrs)
    |> cast_assoc(:master, required: true, with: &(Variant.update_master_changeset(&1, product, &2)))
    |> validate_available_on_lt_discontinue_on
  end

  defp validate_available_on_lt_discontinue_on(changeset) do
    changeset
    |> Date.validate_lt_date(:available_on, changed_discontinue_on(changeset))
  end

  defp changed_discontinue_on(changeset) do
    changed_master = get_change(changeset, :master)
    if changed_master do
      get_change(changed_master, :discontinue_on) || changed_master.data.discontinue_on
    else
      changeset.data.master.discontinue_on
    end
  end
  
  defp parse_tags(attrs)  do
    (attrs["tags"] || "")
    |> String.split(",")
    |> Enum.map(&String.trim/1)
    |> Enum.reject(& &1 == "")
    |> Enum.map(&get_or_insert_tag/1)
  end
  
  defp get_or_insert_tag(name) do
    Repo.get_by(Tag, name: name) || maybe_insert_tag(name)
  end
  
  defp maybe_insert_tag(name) do
    %Tag{}
    |> change(name: name)
    |> unique_constraint(:name)
    |> Repo.insert
    |> case do
      {:ok, tag} -> tag
      {:error, _} -> Repo.get_by!(Tag, name: name)
    end
  end
end

## Here my product controller 

def edit(conn, %{"id" => id}) do
    product = Shop.Query.Product.get!(Repo, id) |> Repo.preload([:master, :product_option_types, :product_categories, :tags])
    changeset = Product.changeset(product, %{})
    render(conn, "edit.html", product: product, changeset: changeset)
  end

## and here the form

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

Thanks

Judging by the error message

list in Phoenix.Html and templates may only contain integers representing bytes , binaries, or other list, got invalid entry: #Ecto.Changeset <action: :replace, changes: %{}, errors [], data: #Shop.Catalog.Tag<>, valid?: true

you are trying to render an ecto changeset for Shop.Catalog.Tag somewhere in your template.

1 Like

The problem is that I need to recover the tags that are associated with the product schema

many_to_many :tags, Tag, join_through: ProductTag, on_replace: :delete

in product changeset i have this

|> put_assoc(:tags, parse_tags(attrs))

an the function to parse the tags.

defp parse_tags(attrs)  do
    (attrs["tags"] || "")
    |> String.split(",")
    |> Enum.map(&String.trim/1)
    |> Enum.reject(& &1 == "")
    |> Enum.map(&get_or_insert_tag/1)
  end
  
  defp get_or_insert_tag(name) do
    Repo.get_by(Tag, name: name) || maybe_insert_tag(name)
  end
  
  defp maybe_insert_tag(name) do
    %Tag{}
    |> change(name: name)
    |> unique_constraint(:name)
    |> Repo.insert
    |> case do
      {:ok, tag} -> tag
      {:error, _} -> Repo.get_by!(Tag, name: name)
    end
  end

when edit the product schema, raise previous error, i use this in the form

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

for create and edit, where is the error?

for create and edit, where is the error?

The error comes from a view, where Phoenix.HTML or something similar tries to render an %Ecto.Changeset{} and fails.

Can you please post the full error with its stacktrace?