gpt4 book ai didi

elixir - 在 Phoenix 中处理嵌套表单/ecto 变更集的正确方法是什么?

转载 作者:行者123 更新时间:2023-12-03 20:45:11 25 4
gpt4 key购买 nike

我正在 Phoenix 编写一个简单的 CRUD 应用程序,允许管理员在创建新组织时为其提供初始员工帐户。

组织和用户之间的关系实际上是多对多的。

我想出了以下内容:

  • 用户架构:
    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
  • 接线台org_staff_users和相应的 Ecto 模式user_idorg_id
  • Controller 带有以下 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 上插入的变更集的规范方式应该是什么。 ,同时能够
    在验证错误时再次将其传递给 View 。

    不清楚我是应该使用一个变更集(以及如何使用?)还是明确地
    每个实体三个变更集( UserOrg 和联结表)。

    鉴于每个
    模型/架构是否定义了自己的特定验证?

    我在提交表单时收到的参数都在 %{"org" => ...}
    map ,包括实际上与 user 相关的 map .我该怎么办
    正确创建表单?

    我已经阅读了最近更新的 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。

    任何提示将非常感谢。

    最佳答案

    现在,除了在事务中完成所有操作之外,您别无选择。您将在事务内创建一个组织,该组织拥有自己的变更集,如果可行,您将创建每个员工。像这样的东西:

    if organization_changeset.valid? and Enum.all?(staff_changesets, & &1.valid?) do
    Repo.transaction fn ->
    Repo.insert!(organization_changeset)
    Enum.each staff_changesets, &Repo.insert!/1)
    end
    end

    注意我在做 valid?检查非理想的变更集,因为它不考虑约束。如果变更集中存在约束,则需要使用 Repo.insert (没有爆炸 !)。

    请记住,这在 Ecto 2.0 上会容易得多。在 Ecto master 上,我们已经通过变更集支持belongs_to,这意味着您可以通过生成中间和最终关联来明确地做到这一点:
    <%= inputs_for f, :org_staff_users, fn org_staff -> %>
    <%= inputs_for org_staff, :user, fn user -> %>
    # Your user form here
    <% end %>
    <% end %>

    但是,我们还将支持 many_to_many,这将使其完全直接。

    关于elixir - 在 Phoenix 中处理嵌套表单/ecto 变更集的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34443514/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com