如何修改 many_to_many 变更集中的 join_defaults 值?

问题描述

我在 UsersOrganizations 之间建立了多对多关系,使用自定义 Members 架构作为连接表。

简化模式:

schema "members" do
  field :role,:string
  field :organization_id,:id
  field :user_id,:id
end

schema "organizations" do
  field :name,:string
  many_to_many :users,App.Users.User,join_through: App.Organizations.Members,join_defaults: [role: "read"]
end

schema "users" do
  many_to_many :organizations,App.Organizations.Organization,join_defaults: [role: "read"]
end

问题:如何在创建新变更集时修改成员的 role 参数? IE。当我创建新用户(和组织)时,如何在此处传递 role 使其成为认值以外的值?

user = User.changeset(%User{},%{"organizations": [%{"name": "test org"}]}) 
|> Ecto.Changeset.cast_assoc(:organizations,with: &App.Organizations.Organization.changeset/2)

解决方法

根据(the docs):

注意:通过关联是只读的。例如,您不能使用 Ecto.Changeset.cast_assoc/3 通过关联修改。

我通常用 Ecto.Multi 处理这些事情:

    user_attrs = %{"name" => "Alice"}
    organization_attrs = %{"name" => "The Club"}
    member_attrs = %{"role" => "Manager"}

    Ecto.Multi.new()
    |> Ecto.Multi.insert(:user,User.changeset(%User{},user_attrs))
    |> Ecto.Multi.insert(
      :organization,Organization.changeset(%Organization{},organization_attrs)
    )
    |> Ecto.Multi.insert(
      :member,fn %{user: %{id: user_id}},%{organization: %{id: organization_id}} ->
        Member.changeset(
          %Member{},Enum.into(member_attrs,%{"user_id" => user_id,"organization_id" => organization_id})
        )
      end
    )
    |> Repo.transaction()
    |> case do
      {:ok,%{user: user,organization: organization,member: member}} -> {:ok,user}
      {:error,_,changeset,_} -> {:error,changeset}
    end

我没有尝试编译该代码,因此可能需要调整。