У меня есть настройка схемы Ecto с ассоциацией has_many
. Я хочу иметь возможность динамически добавлять/удалять к нему ассоциации, сохраняя первоначальную ассоциацию.
Я пытался использовать Ecto.Changeset.put_assoc/4
, и это работает при загрузке начальной ассоциации, однако каждый последующий вызов переопределяет начальную ассоциацию.
change_one = Changeset.put_assoc(changeset, :foo_assocs, [%{index: 1}])
...
foo_assocs: [
#Ecto.Changeset<
action: :insert,
changes: %{index: 1},
errors: [],
data: #Linker.CustomForms.FooAssoc<>,
valid?: true
>
]
...
Затем, если я снова вызову его с другой связанной записью, чтобы добавить:
change_two = Changeset.put_assoc(changeset_one, :foo_assocs, [%{index: 2}])
...
foo_assocs: [
#Ecto.Changeset<
action: :insert,
changes: %{index: 2},
errors: [],
data: #Linker.CustomForms.FooAssoc<>,
valid?: true
>
]
...
Моя первая запись перезаписана.
Это предполагаемое поведение put_assoc/4
, поскольку он предназначен для работы с полным набором данных. На самом деле ваш вопрос очень хорошо описан в документах Ecto: https://hexdocs.pm/ecto/Ecto.Changeset.html#put_assoc/4-example-adding-a-comment-to-a-post
A map or keyword list can be given to update the associated data as long as they have matching primary keys. For example, put_assoc(changeset, :comments, [%{id: 1, title: "changed"}]) will locate the comment with :id of 1 and update its title. If no comment with such id exists, one is created on the fly. Since only a single comment was given, any other associated comment will be replaced.
Таким образом, вы можете объединить существующие данные с новыми данными и использовать put_assoc/4
или вы можете работать над своей единственной ассоциацией, как в следующем примере, где вы устанавливаете ассоциацию от своего ребенка.
changeset = %__MODULE__{} |> has_many(:foo_assoc, [%{index: 1}])
%FooChild{index: 2}
|> Ecto.Changeset.change()
|> Ecto.Changeset.put_assoc(:parent, changeset)
|> Repo.insert!()
Но я бы рекомендовал прочитать ссылку выше для более подробного описания того, как использовать put_assoc/4
и has_many
.