【问题标题】:Updating association with cast_assoc更新与 cast_assoc 的关联
【发布时间】:2021-05-30 10:03:51
【问题描述】:

我有两张桌子UsersCompanies。用户属于一个公司,一个公司有很多用户。

我有一个表单,我可以在其中将用户添加到公司,它被实现为嵌套表单 (inputs_for),所以在公司的变更集中,我调用了 cast_assoc

def changeset(company, attrs) do
    company
    |> cast(attrs, [:name, :email])
    |> validate_required([:name, :email])
    |> cast_assoc(:users, with: &User.company_admin_changeset/2)
  end

我想要做的是,当我将已经存在的用户添加到公司时,它应该更新用户的 company_id(foreign_key)。如果用户不存在,只需创建一个。

看着我的要求,我开始认为不可能从 cast_assoc 中做到这一点。所以,我用了transaction

  def create_company(attrs \\ %{}) do
    Repo.transaction(fn ->
      cmp =
        Company.changeset(%Company{}, %{name: attrs["name"], email: attrs["email"]})
        |> Repo.insert!()

      Enum.each(attrs["users"], fn {_, user} ->
        case Accounts.get_user_by_email(user["email"]) do
          nil ->
            User.company_admin_changeset(%User{}, %{email: user["email"], company_id: cmp.id})
            |> Repo.insert!()

          account ->
            account |> Ecto.Changeset.change(company_id: cmp.id) |> Repo.update!()
        end
      end)
    end)
  end

但如果可能的话,你能告诉我该怎么做吗?

【问题讨论】:

  • 我认为你的方法是正确的——你的用例似乎不属于协会:on_replace 选项所描述的那些。但是,您可以稍微清理一下流程以利用 Ecto.Repo.get_by/3Ecto.Repo.insert_or_update/2

标签: elixir ecto


【解决方案1】:

我使用了 upserts,但我必须根据用户是否存在来运行自定义方法,所以我仍在使用旧代码进行事务处理

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-26
    • 2014-07-15
    • 1970-01-01
    • 2011-06-18
    相关资源
    最近更新 更多