I have Events, which can have many Contacts. On the Event edit/new form I have a multiple select box where a user can choose Contacts which should be associated with the event.
I have setup associations in the schema and database migrations. I got the form working as well with the group select. When you select a bunch of groups and then click new or edit, it succeeds fine. However the event_id in the Contacts table doesn’t change and when I go back to edit Event there are no groups selected.
In my child changesets I have been using assoc_constraint but I understand that is only for the receiving end of the belongs_to relationship. What is the most idiomatic way to update my Contacts table to be correctly associated with the Event?
Event Schema
defmodule App.Event do
use Ecto.Schema
import Ecto.Changeset
schema "events" do
field :name, :string
field :description, :string
has_many :contacts, App.Contact
timestamps()
end
@doc false
def changeset(event, attrs) do
required_fields = [:name]
optional_fields = [:description]
event
|> cast(attrs, required_fields ++ optional_fields)
|> validate_required(required_fields)
end
end
Contact Schema
defmodule App.Contact do
use Ecto.Schema
import Ecto.Changeset
schema "contacts" do
field :email, :string
field :name, :string
field :phonenumber, :string
belongs_to :event, App.Event
timestamps()
end
@doc false
def changeset(contact, attrs) do
required_fields = [:name, :phonenumber]
optional_fields = [:email]
contact
|> cast(attrs, required_fields ++ optional_fields)
|> validate_required(required_fields)
end
end
Event Migration
defmodule App.Repo.Migrations.CreateEvents do
use Ecto.Migration
def change do
create table(:events) do
add :name, :string, null: false
add :description, :text
timestamps()
end
create unique_index(:events, [:name])
end
end
Contact Migration
defmodule App.Repo.Migrations.CreateContacts do
use Ecto.Migration
def change do
create table(:contacts) do
add :name, :string, null: false
add :email, :string
add :phonenumber, :string, null: false
add :event_id, references(:events, on_delete: :delete_all)
timestamps()
end
end
end