(RuntimeError) you are attempting to change relation, but missing data?

What am I doing wrong?

if you follow along you will see that from the looks of it everything is proloaded so I’m not sure what data is missing.

pry(13)> changeset.data
%Beffect.Accounts.User{__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
 active: true,
 department: %Beffect.Organization.Department{__meta__: #Ecto.Schema.Metadata<:loaded, "departments">,
  id: 19, inserted_at: ~N[2017-09-25 19:27:52.066164], name: "Early Childhood",
  programs: #Ecto.Association.NotLoaded<association :programs is not loaded>,
  slug: "early-childhood", updated_at: ~N[2017-09-25 19:27:52.083220]},
 department_id: 19, email: "jchernoff@impactnw.org", first_name: "Josh", id: 1,
 inserted_at: ~N[2017-09-22 19:29:50.581900], invite_confirmed_at: nil,
 invite_sent_at: nil, invite_token: nil, invite_token_raw: nil,
 last_name: "Chernoff", pass: nil, pass_confirmation: nil,
 pass_reset_confirmed_at: #Ecto.DateTime<2017-09-26 16:58:00>,
 pass_reset_sent_at: nil, pass_reset_token: nil, pass_reset_token_raw: nil,
 programs: [%Beffect.Organization.Program{__meta__: #Ecto.Schema.Metadata<:loaded, "programs">,
   department: #Ecto.Association.NotLoaded<association :department is not loaded>,
   department_id: 19, id: 1, inserted_at: ~N[2017-09-28 20:20:47.683263],
   name: "foo", slug: "foo", updated_at: ~N[2017-09-28 20:20:47.705277],
   users: #Ecto.Association.NotLoaded<association :users is not loaded>},
  %Beffect.Organization.Program{__meta__: #Ecto.Schema.Metadata<:loaded, "programs">,
   department: #Ecto.Association.NotLoaded<association :department is not loaded>,
   department_id: 19, id: 2, inserted_at: ~N[2017-09-28 20:43:23.748980],
   name: "aaaaaaa", slug: "fffffff", updated_at: ~N[2017-09-28 20:49:18.930080],
   users: #Ecto.Association.NotLoaded<association :users is not loaded>}],
 updated_at: ~N[2017-09-27 19:58:27.351934]}
pry(14)>
nil
pry(15)>
nil
pry(16)>
nil
pry(17)> programs
[%Beffect.Organization.Program{__meta__: #Ecto.Schema.Metadata<:loaded, "programs">,
  department: #Ecto.Association.NotLoaded<association :department is not loaded>,
  department_id: 19, id: 1, inserted_at: ~N[2017-09-28 20:20:47.683263],
  name: "foo", slug: "foo", updated_at: ~N[2017-09-28 20:20:47.705277],
  users: [%Beffect.Accounts.User{__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
    active: true,
    department: #Ecto.Association.NotLoaded<association :department is not loaded>,
    department_id: 19, email: "jchernoff@impactnw.org", first_name: "Josh",
    id: 1, inserted_at: ~N[2017-09-22 19:29:50.581900],
    invite_confirmed_at: nil, invite_sent_at: nil, invite_token: nil,
    invite_token_raw: nil, last_name: "Chernoff", pass: nil,
    pass_confirmation: nil,
    pass_reset_confirmed_at: #Ecto.DateTime<2017-09-26 16:58:00>,
    pass_reset_sent_at: nil, pass_reset_token: nil, pass_reset_token_raw: nil,
    programs: #Ecto.Association.NotLoaded<association :programs is not loaded>,
    updated_at: ~N[2017-09-27 19:58:27.351934]}]}]
pry(18)>
nil
pry(19)>
nil
pry(20)>
nil
pry(21)> changeset |> put_assoc(:programs, programs)
** (RuntimeError) you are attempting to change relation :programs of
Beffect.Accounts.User, but there is missing data.

If you are attempting to update an existing entry, please make sure
you include the entry primary key (ID) alongside the data.

If you have a relationship with many children, at least the same N
children must be given on update. By default it is not possible to
orphan embed nor associated records, attempting to do so results in
this error message.

If you don't desire the current behavior or if you are using embeds
without a primary key, it is possible to change this behaviour by
setting `:on_replace` when defining the relation. See `Ecto.Changeset`'s
section on related data for more info.

    (ecto) lib/ecto/changeset/relation.ex:176: Ecto.Changeset.Relation.on_replace/2
    (ecto) lib/ecto/changeset/relation.ex:299: Ecto.Changeset.Relation.reduce_delete_changesets/5
    (ecto) lib/ecto/changeset.ex:1092: Ecto.Changeset.put_relation/5
    (stdlib) erl_eval.erl:670: :erl_eval.do_apply/6
    (iex) lib/iex/evaluator.ex:219: IEx.Evaluator.handle_eval/5
    (iex) lib/iex/evaluator.ex:200: IEx.Evaluator.do_eval/3
    (iex) lib/iex/evaluator.ex:178: IEx.Evaluator.eval/3
    (iex) lib/iex/evaluator.ex:77: IEx.Evaluator.loop/1
    (iex) lib/iex/evaluator.ex:21: IEx.Evaluator.init/4
    (iex) lib/iex/pry.ex:55: IEx.Pry.pry/2
    (beffect) lib/beffect/accounts/user.ex:47: Beffect.Accounts.User.put_programs/2
    (beffect) lib/beffect/accounts/user.ex:40: Beffect.Accounts.User.changeset/2
    (beffect) lib/beffect/accounts/accounts.ex:161: Beffect.Accounts.update_user/2
    (beffect) lib/beffect_web/controllers/user_controller.ex:107: BeffectWeb.UserController.update/2
    (beffect) lib/beffect_web/controllers/user_controller.ex:1: BeffectWeb.UserController.action/2
    (beffect) lib/beffect_web/controllers/user_controller.ex:1: BeffectWeb.UserController.phoenix_controller_pipeline/2
    (beffect) lib/beffect_web/endpoint.ex:1: BeffectWeb.Endpoint.instrument/4
    (phoenix) lib/phoenix/router.ex:278: Phoenix.Router.__call__/1
    (beffect) lib/beffect_web/endpoint.ex:1: BeffectWeb.Endpoint.plug_builder_call/2

Hmm, you are not showing any code that I can see? Where is the error?

The error is not because you are not preloading. The error is because you preloaded and then cast_assoc or put_assoc or similar is putting less data then you originally had and Ecto wants you to explicitly choose what happens with the deleted/replaced data.

9 Likes

ok so this is more a problem with the
many_to_many :programs, Beffect.Organization.Program, join_through: "programs_users"
not including how to deal with on_replace ?

1 Like

thank you that lead me to the right info. I was more confused by the message of the error and let that distracted me from looking in the right direction.

2 Likes