Я пишу простое приложение CRUD в Фениксе, где администраторы при создании новой организации могут предоставить ему исходную учетную запись сотрудника.Каков правильный способ обработки вложенных форм/ecto изменений в Phoenix?
Фактически взаимоотношения между организациями и пользователями много для многих.
я придумал следующее:
схема пользователя:
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.
Организация схемы:
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 стол
org_staff_users
и соответствующий Ecto схемы сuser_id
иorg_id
Контроллер со следующими
new
действия:def new(conn, _params) do data = %Org{org_staff_users: [%User{}]} changeset = Org.provisioning_changeset(data) render(conn, "new.html", changeset: changeset) end
шаблона со следующей выдержке:
<%= 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 %>
До сих пор так хорошо, форма проявления красиво.
Проблема заключается в том, что я не понимаю, каков должен быть канонический способ построения набора изменений, который я собираюсь вставить на create
, имея возможность передать его снова на просмотр при ошибках проверки.
Неясно, должен ли я использовать одну ревизию (и как?) Или явно три ревизии за каждый объект (User
, Org
и таблицу перехода).
Как проверить изменения для такой комбинированной формы, учитывая, что каждая модель/схема имеет свои собственные конкретные проверки?
Параметры, которые я получаю при отправке формы, находятся в пределах %{"org" => ...}
карта, включая те, которые на самом деле связаны с user
. Как я должен правильно создать форму?
Я прочитал недавно обновленный http://blog.plataformatec.com.br/2015/08/working-with-ecto-associations-and-embeds/ , но я все равно смущен.
FWIW, я нахожусь на Phoenix 1.0.4, Phoenix Ecto 2.0 и Phoenix HTML 2.3.0.
Любые советы были бы весьма признательны.
@jose_valim, было бы здорово, чтобы разъяснить это в блоге, или ссылку на http://blog.plataformatec.com.br/2015/12/ecto-v1 -1-released-and-ecto-v2-0-plans/где он более четко обозначен. У меня была такая же путаница. Но, ох, я в восторге от Ecto 2.0. –
@ José Valim, первое спасибо за всю большую работу, поставленную в Phoenix, действительно перспективный проект. Что касается вопроса о вложенных формах, я надеюсь, вы представите больше информации об этом в документации API. Генератор создает объекты с отношениями к другим объектам (например, сообщения для пользователей), но не существует поля формы или метода, позволяющих назначать сообщение пользователю при написании нового сообщения. Пожалуйста, предоставьте дополнительную информацию об этом. –