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

How to modify join_defaults values in many_to_many changeset?

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

简化架构:

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_through: App.Organizations.Members, 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):

Note :through associations are read-only. For example, you cannot use Ecto.Changeset.cast_assoc/3 to modify through associations.

我通常用 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

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