当前位置:  开发笔记 > 前端 > 正文

在凤凰城处理嵌套表格/外部变更集的正确方法是什么?

如何解决《在凤凰城处理嵌套表格/外部变更集的正确方法是什么?》经验,为你挑选了1个好方法。

我正在凤凰城编写一个简单的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 Schema with user_idorg_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 %>
            

    Oops, something went wrong! Please check the errors below:

      <%= for {attr, message} <- f.errors do %>
    • <%= humanize(attr) %> <%= message %>
    • <% end %>
    <% 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,同时能够在验证错误时将其再次传递给视图.

目前还不清楚我是否应该使用一个变更(以及如何?)或每每一个实体明确3的变更(User,Org和结表).

如果每个模型/模式都定义了自己的特定验证,我如何验证这种组合形式的更改?

我在提交表格时接​​受的参数都在%{"org" => ...} 地图内,包括实际上与a相关的参数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上.

任何提示将非常感谢.



1> José Valim..:

现在,除了在事务中执行所有操作之外,您没有任何其他选项.您将在事务中创建一个组织,该组织具有自己的变更集,如果可行,则创建每个员工.像这样的东西:

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上,我们已经通过changesets支持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,这将使它完全直截了当.

推荐阅读
小白也坚强_177
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有