是否可以在 many_to_many 关联中添加其他字段?

Will it be possible to add additional fields in many_to_many association in ecto?

我是 Ecto 的新手。我在 Ecto 模式中定义了三个 table,分别称为 User、Role 和 UserRole。在 UserRole 中,我需要更新附加字段(例如 "status")以关联用户和角色 table,这将在 UserRole [=125] 中创建一个条目=].

// User Schema
schema "users" do
    field :first_name, :string
    field :last_name, :string
    field :email, :string

    many_to_many :roles, Role, join_through: "userroles"
end

// Role Schema
schema "roles" do
    field :code, :string
    field :description, :string

    many_to_many :users, User, join_through: "userroles"
end

// UserRole Schema
schema "userroles" do
    field :is_default, :boolean, default: false
    field :status, :string
    field :user_id, :id
    field :role_id, :id

    belongs_to :users, User, define_field: false
    belongs_to :roles, Role, define_field: false
end

// 以下是我完成的步骤

  1. 使用 iex -S mix
  2. 打开 iex
  3. 在用户 table 中插入了一条记录。

    一个。 userChangeset = User.changeset(%User{}, %{email: "xyz@gmail.com", first_name: "xyz", last_name: "z"}) b. user1 = Repo.insert!(userChangeset)

  4. 在角色 table 中插入了一条记录。

    一个。 roleChangeset = Role.changeset(%Role{}, %{code: "CON", description: "Consumer"}) b. role1 = Repo.insert!(roleChangeset)

  5. 现在一切正常,我在变量 user1 中有用户记录,在变量 role1 中有角色记录。
  6. 现在我需要关联这两个记录以在 UserRole Table 中插入一条记录。将在关联 user1 和 role1 记录时自动创建
  7. 通过在 iex

    使用以下命令关联 user1 和 role1 记录

    一个。 userRoleAssoc = user1 |> Repo.preload(:roles) |> Ecto.Changeset.change() |> Ecto.Changeset.put_assoc(:roles, [role1]) |> Repo.update !

  8. 是的,它在 UserRole 中插入一条记录,如下所示

  9. 但这里的问题是,我需要在关联时插入 status 字段。我该怎么做。
  10. 我尝试更新 UserRole 记录

    一个。 fetchUserRole = Repo.get_by(UserRole, id: 1)

    b。 fetchUserRole = %{ fetchUserRole |状态:"Active"}

    c。 fetchUserRole |> Ecto.Changeset.change() |> Repo.update

  11. 它给出了以下结果。结果它得到了更新但没有反映在我的数据库中。结果与上图一样。

    {:好的, %用户角色{ meta: #Ecto.Schema.Metadata<:loaded, "userroles">, 公司:#Ecto.Association.NotLoaded, 编号:1, is_default:错误, role_id: 1, 角色:#Ecto.Association.NotLoaded, 状态:"Active", user_id: 1, 用户:#Ecto.Association.NotLoaded }}

  12. 我的问题是,如果是many_to_many关联,有没有办法在关联时插入字段值。如果是意味着,如何做到这一点。

要真正回答 #11,有一个关于您的业务逻辑的问题需要回答:

当您的用户将用户分配给角色时,他们是否创建 新角色?或者只是从预定义角色中选择?

我想应该是后者。如果是这样,我想您可以执行以下操作...

defmodule YourApp.User do
  use Ecto.Schema
  import Ecto.Changeset

  schema "users" do
    ...
    has_many :user_roles, YourApp.UserRole
  end

  def changeset(user, params) do
    user
    |> cast_things...
    |> cast_assoc(:user_roles)
  end
end

...因为您的用户永远不会更改可用的角色。只是用户角色。这会让你做类似...

用户 = YourApp.Repo.get(YourApp.User, 1)

user
|> YourApp.User.changeset(%{user_roles: [%{role_id: 1, status: "Active"}]})
|> YourApp.Repo.update

有这个可能。但是,我个人发现使用 cast_assoc 有时很难全神贯注,尤其是考虑到 the preloading required and nuanced rules to process,所以我倾向于直接处理连接表。这就是为什么我在上面的评论中提到我很困惑为什么 #9 和 #10 在上面不起作用。