如果模型有关联,如何通过 Ecto 复制一行?

How to duplicate a row via Ecto if a model has associations?

我有一个模型有几个 "belongs_to" 和 "has_many" 我想用新生成的 "id" 和其他字段的新值来复制它。

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"}))

和错误:

(RuntimeError) attempting to cast or change association `my_assoc1` from `MyModel` that was not loaded. 
Please preload your associations before manipulating them through changesets

我不想预加载每个关联。 此外,如果我希望复制的模型实例具有 my_assoc1_id,这是一个整数,与原始实例相同,也就是说,是否加载关联并不重要。

我也不想从变更集中删除每个关联。

怎么做?

不能 manipulate/cast 直接关联belongs_tohas_many。这些关联是一个抽象层,因此您可以更轻松地操作数据。

例如:

schema "my_model" do
    belongs_to :my_field, Example
end

如果查看数据库或迁移,您会注意到创建了一个名为 my_field_id 的字段,其中包含指向另一个 table.

的外键

如果您想克隆一个具有所有关联的实体,您只需创建一个变更集以确保外键也被强制转换:

def changeset(my_model, params \ %{}) do
    user
    |> cast(params, [:my_field_id])
    |> validate_required([:my_field_id])
    |> foreign_key_constraint(:my_field_id)
  end