更新与 cast_assoc 的关联

问题描述

我有两个表 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

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

解决方法

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