Ich schreibe eine einfache CRUD-App in Phoenix, wo Admins, wenn sie eine neue Organisation erstellen, sie mit einem anfänglichen Mitarbeiterkonto versehen können.Was ist der richtige Umgang mit geschachtelten Formularen/ecto changesets in Phoenix?
Effektiv die Beziehung zwischen Organisationen und Benutzern ist viele zu viele.
ich kam mit den folgenden:
Benutzer Schema:
defmodule MyApp.User do use MyApp.Web, :model schema "users" do field :name, :string field :email, :string field :password, :string, virtual: true field :password_hash, :string end def changeset(...) # validate email, password confirmation etc.
Organisationsschema:
defmodule MyApp.Org do use MyApp.Web, :model schema "orgs" do field :official_name, :string field :common_name, :string has_many :org_staff_users, MyApp.OrgStaffUser has_many :users, through: [:org_staff_users, :user] end def changeset(model, params \\ :empty) do model |> cast(params, ~w(official_name common_name), []) end def provisioning_changeset(model, params \\ :empty) do model |> changeset(params) |> cast_assoc(:org_staff_users, required: true) end
Junction Tabelle
org_staff_users
und die entsprechende Ecto-Schema mituser_id
undorg_id
-Controller mit der folgenden
new
Aktion:def new(conn, _params) do data = %Org{org_staff_users: [%User{}]} changeset = Org.provisioning_changeset(data) render(conn, "new.html", changeset: changeset) end
Vorlage mit dem folgenden Auszug:
<%= form_for @changeset, @action, fn f -> %> <%= if @changeset.action do %> <div class="alert alert-danger"> <p>Oops, something went wrong! Please check the errors below:</p> <ul> <%= for {attr, message} <- f.errors do %> <li><%= humanize(attr) %> <%= message %></li> <% end %> </ul> </div> <% end %> <%= text_input f, :official_name, class: "form-control" %> <%= text_input f, :common_name, class: "form-control" %> <%= inputs_for f, :org_staff_users, fn i -> %> <%= text_input f, :email, class: "form-control" %> <%= text_input f, :password, class: "form-control" %> <%= text_input f, :password_confirmation, class: "form-control" %> <% end %> <%= submit "Submit", class: "btn btn-primary" %> <% end %>
So weit, so gut, die Form schön angezeigt.
Das Problem ist, dass ich nicht wirklich verstehen, was der kanonische Weg sein sollte, die changeset zu bauen Ich bin etwa auf create
einfügen, während in der Lage zu sein es zu der Ansicht wieder passiert auf Validierungsfehler.
Es ist unklar, ob ich ein changeset (und wie?) Oder explizit drei Differenzmengen pro jede Einheit (User
, Org
und die Verknüpfungstabelle) verwendet werden soll.
Wie validiere ich die Änderungen für ein solches kombiniertes Formular, vorausgesetzt, dass jedes Modell/Schema seine eigenen spezifischen Validierungen definiert hat?
Die params ich auf Absenden des Formulars receieve sind alle innerhalb von %{"org" => ...}
Karte, die, einschließlich die in der Tat zu einem user
verwandt. Wie sollte ich das Formular richtig erstellen?
Ich habe die kürzlich aktualisierte http://blog.plataformatec.com.br/2015/08/working-with-ecto-associations-and-embeds/ gelesen, aber ich bleibe verwirrt, egal.
FWIW, ich bin auf Phoenix 1.0.4, Phoenix Ecto 2.0 und Phoenix HTML 2.3.0.
Alle Tipps würden sehr geschätzt werden.
@jose_valim, wäre es toll, diese in der Blog-Post zu klären, oder einen Link zu http://blog.plataformatec.com.br/2015/12/ecto-v1 -1-released-und-ecto-v2-0-Pläne/wo es klarer umrissen wird. Ich hatte die gleiche Verwirrung. Aber oh Junge bin ich aufgeregt für Ecto 2.0. –
@ José Valim, zuerst vielen Dank für die großartige Arbeit in Phoenix, ein wirklich vielversprechendes Projekt. Was das Problem verschachtelter Formulare anbelangt, hoffe ich, dass Sie in Ihrer API-Dokumentation weitere Informationen dazu finden. Der Generator erstellt Entitäten mit Beziehungen zu anderen Entitäten (sagen wir Beiträge zu Benutzern), aber es gibt kein Formularfeld oder eine Methode, die es ermöglicht, einem Benutzer beim Schreiben eines neuen Beitrags einen Beitrag zuzuweisen. Bitte geben Sie weitere Informationen dazu an. –