Ecto inline embeds help

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

What is your lib/app/accounts/form.ex files contents?

That’s the file copy/pasted into the first post. Probably confusing because I changed the module name :sweat_smile:. I’ll edit that.

Ah, duh. ^.^;

I’m unsure off hand, I’ve never used embedded tables yet…

Should the embedded_schema have a @primary_key false added?

@primary_key - configures the schema primary key. It expects a tuple {field_name, type, options} with the primary key field name, type (typically :id or :binary_id, but can be any type) and options. Defaults to {:id, :id, autogenerate: true}. When set to false, does not define a primary key in the schema unless composite keys are defined using the options of field.

Well, that seems to have answered both my questions! Added @primary_key false and the id error went away, now it says I can’t call schema twice in one module. Thanks for your help!