Ich habe ein Foo
Schema in meiner App, die has_many
des Schemas Bar
.Dynamische Anzahl der Einsätze mit Ecto.multi
schema "foos" do
field :content, :string
has_many :bars, MyApp.Content.Bar, foreign_key: :foo_id
end
schema "bars" do
field :content, :string
belongs_to :foo, MyApp.Content.Foo, foreign_key: :foo_id
end
Ich möchte eine Funktion, die eine ID für eine Foo
nimmt, eine Kopie dieser Foo
erstellt und fügt sie, und dann erstellt Kopien aller zugehörigen Bar
s mit dem neuen Foo
. Bei einem Foo mit vielen untergeordneten Balken kopiert diese Funktion das Foo und alle diese Balken auf einmal.
Ich benutze Ecto.Multi für solche Dinge, aber ich bin mir nicht sicher, wie ich es für eine variable Anzahl von Aktionen einrichten soll. Bisher habe ich dies:
resolve fn (%{foo_id: foo_id}, _info) ->
oldfoo = Repo.get!(Foo, foo_id)
multi =
Multi.new
|> Multi.run(:foo, fn %{} ->
MyApp.Content.create_foo(%{
content: oldfoo.content
}) end)
|> Multi.run(:bars, fn %{foo: foo} ->
query =
from b in Bar,
where: b.foo_id == ^foo.id,
select: b.id
bars = Repo.all(query) # returns a list of id/ints like [2,3,6,7,11...]
Enum.map(bars, fn barid ->
bar = Repo.get(Bar, barid)
Bar.changeset(%Bar{}, %{
content: bar.content,
foo_id: foo.id
})
|> Repo.insert()
end)
end)
case Repo.transaction(multi) do
{:ok, %{foo: foo}} ->
{:ok, foo}
{:error, _} ->
{:error, "Error"}
end
dies ein Fehler wirft:
** (exit) an exception was raised:
** (CaseClauseError) no case clause matching: [ok: %MyApp.Content.Foo...
Gibt es eine vernünftige Möglichkeit, dies innerhalb Ecto.Multi zu tun?