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