I’m finding it very difficult to figure out how to update an embedded struct that is in a nested embeds_many array.
Here’s the basic schema…
(Main row in postgres) Gathering → Activities (embeds_many Activity on Gathering) → rsvp (embeds_many ActivityRsvp on Activity)
The struggle to update the records in the rsvp collection is real. I’ve spent days reading methods to do this.
Ultimately, the insert works fine, but I can’t figure out how to make put_embed update the record.
A key difficulty was (which I believe is a bug), autogenerate_id was not working for the nested embeds_many, so I had to generate my own primary keys. This leads me to believe that this feature simply isn’t supported?
So to recap, if I bypass the error by generating my own primary key I can get insert to work fine using rsvps ++ [rcs], but I can’t get updates to work. Depending on the hack I try, I get a cornucopia of different errors. usually around get_change/6
Models:
schema "gatherings" do
embeds_many :activities, Activity
end
# Activity
embedded_schema do
embeds_many :rsvp, ActivityRsvp
end
# ActivityRsvp
embedded_schema do
field :username, :string
field :attending, :boolean
end
def change_rsvp_status_for_user(%Gathering{} = gathering, %Activity{ rsvp: rsvps } = activity, %{ username: username, attending: attending } = rsvp_params) do
rcs = case get_rsvp_status_for_user(activity, username) do
{:unknown, changeset} -> changeset
{:ok, %ActivityRsvp{id: id} = r, _attendance_list} -> ActivityRsvp.changeset(r, rsvp_params)
end
case rcs.valid? do
true -> acs = activity
|> Activity.changeset
|> put_embed(:rsvp, [rcs])
{:ok, a} = update_activity(gathering, acs )
get_rsvp_status_for_user(a, username)
false -> {:error, rcs}
end
end
test/geeks/activities_test.exs:69 ** (Ecto.NoPrimaryKeyValueError) struct `%ActivityRsvp{attending: true, comment: nil, **id: nil,** inserted_at: nil, no_show: false, updated_at: nil, username: "greybeard_prime"}` is missing primary key value stacktrace: (ecto) lib/ecto/embedded.ex:155: anonymous fn/3 in Ecto.Embedded.autogenerate_id/5