2017-05-29 6 views
0

In meinem Phoenix App Ich habe folgende Schemata:Ecto.Multi ussage

defmodule TattooBackend.Accounts.Account do 
    schema "accounts" do 
    field :email, :string 
    field :crypted_password, :string 
    field :password, :string, virtual: true 
    field :password_confirmation, :string, virtual: true 

    timestamps() 
    end 
end 

defmodule TattooBackend.Accounts.Studio do 
    schema "studios" do 
    field :name, :string 

    belongs_to :account, Account 

    timestamps() 
    end 
end 

Jetzt versuche ich, Code zu schreiben, für die in einer Transaktion in die Datenbank Konto und Studio einfügen. Ich benutze Ecto.Multi dafür. Mein Code sieht wie folgt aus:

multi = Multi.new |> 
Multi.insert(:account, Account.changeset(%Account{}, %{email: "[email protected]", password: "password", password_confirmation: "password"})) |> 
Multi.run(:studio, fn %{account: account} -> 
    studio_changeset = Studio.changeset(%Studio{}, %{name: "test", account_id: account.id}) 
    Repo.insert(studio_changeset) 
end) 

Repo.transaction(multi) 

Dieser Code perfekt funktioniert gut, aber ich frage mich, ob es einen Ort, ist es besser zu machen. Ich bin noch immer ziemlich neu in Elixir, also möchte ich wissen, ob etwas besser gemacht werden kann. Danke im Voraus.

+1

Gibt es einen bestimmten Grund, warum Sie 'Multi.run/3' anstelle von' Multi.insert/4' verwenden? –

+0

@JustinWood Ich habe Multi.run benutzt, weil ich den Änderungswert von Studio changeset account_id nach der Kontoerstellung aktualisieren muss. Oder gibt es eine Möglichkeit, das mit Multi.insert zu tun? –

+1

Sie haben Recht. Ich habe nicht bemerkt, dass man die aktuellen Änderungen nicht mit 'Multi.insert/4' bekommen konnte. –

Antwort

1

Für diesen speziellen Code, verwenden Sie put_assoc die neue Studio in Account zu setzen und dann Repo.insert! tun:

Account.changeset(%Account{}, %{email: "[email protected]", password: "password", password_confirmation: "password"}) 
|> Ecto.Changeset.put_assoc(:studios, [Studio.changeset(%Studio{}, %{name: "test"})]) 
|> Repo.insert! 

put_assoc behandelt die richtige account_id im Studio setzen, bevor es eingesetzt wird und die beiden Einsätze werden auch automatisch in einer Transaktion ausgeführt werden.

+0

Der folgende Code: '' 'Konto.ändern (% Konto {},% {E-Mail:" [email protected] ", Kennwort:" Kennwort ", Kennwort_bestätigung:" Kennwort "}) |> Ecto.Changeset.put_assoc (: studio, [Studio.changeset (% Studio {},% {name: "test"})]]> Repo.insert '' ' Fehler zurückgegeben: ** (FunctionClauseError) keine Funktionsklausel passend in anonymous fn/2 in Ecto.Changeset.get_changed/6 –

+1

Hat 'Account'' has_many: studio, TattooBackend.Accounts.Studio'? Wenn nicht, bitte versuchen, das hinzuzufügen und dann ': studio' zu': studios' in 'put_assoc' zu ändern. – Dogbert

+0

'Account' haben' has_one: Studio, Studio' –