I’m trying to create a dynamic form builder using embedded schemas. My hope was to keep it all in one context file for now by using inline embedded schemas, but I’m getting some errors that I don’t understand when doing this. Is something like this supposed to work, or do I have to put the embedded_schema into its own module?
defmodule App.Accounts.Form do
use Ecto.Schema
import Ecto.Changeset
@supported_field_types ~w(text textarea radio checkbox select)
embedded_schema do
embeds_many :fields, Field, on_replace: :delete do
field :field_type, :string
field :field_name, :string
field :options, {:array, :string}
end
end
schema "forms" do
belongs_to :user, App.Accounts.User
timestamps()
end
@doc false
def changeset(%Form{} = form, attrs) do
form
|> cast_embed(:fields, with: &field_changeset/2)
|> validate_required([:fields])
end
defp field_changeset(struct, attrs) do
struct
|> cast(params, [:field_type, :field_name, :options])
|> validate_required([:field_type, :field_name, :options])
|> validate_inclusion(:field_type, @supported_field_types)
|> validate_format(:field_name, ~r/[A-Za-z_]/)
end
end
The error I’m seeing is
** (ArgumentError) field/association :id is already set on schema
(ecto) lib/ecto/schema.ex:1697: Ecto.Schema.put_struct_field/3
(ecto) lib/ecto/schema.ex:1436: Ecto.Schema.field/4
lib/app/accounts/form.ex:14: (module)
(stdlib) erl_eval.erl:670: :erl_eval.do_apply/6
(elixir) lib/kernel/parallel_compiler.ex:121: anonymous fn/4 in Kernel.ParallelCompiler.spawn_compilers/1