I have a model which has several "belongs_to" and "has_many" I want to duplicate it with a newly generated "id" and with a new value of some other field.
m1 = Repo.get(MyModel, 123)
|> Map.delete(:id)
m2 = Repo.insert!(m1, %{my_field: "aaa"})
# or
# m2 = Repo.insert!(MyModel.changeset(m1, %{my_field: "aaa"}))
and error:
(RuntimeError) attempting to cast or change association `my_assoc1` from `MyModel` that was not loaded.
Please preload your associations before manipulating them through changesets
I don't want to have to preload each association.
Besides, why would I have to if I want a duplicated model instance to have my_assoc1_id
, which is an integer, identical to the original instance, that is, whether or not the association is loaded shouldn't matter.
Neither would I want to have to remove each association from a changset.
How to do it?
You cannot manipulate/cast associations like belongs_to
or has_many
directly. These associations are an abstraction layer so that you can manipulate data easier.
For example:
schema "my_model" do
belongs_to :my_field, Example
end
If you take a look in the database or migration, you can notice that a field called my_field_id
was created, containing the foreign key pointing to the other table.
If you want to clone a entity with all associations, you just create a changeset that makes sure that foreign keys get casted too:
def changeset(my_model, params \\ %{}) do
user
|> cast(params, [:my_field_id])
|> validate_required([:my_field_id])
|> foreign_key_constraint(:my_field_id)
end