是否可以在 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
// 以下是我完成的步骤
- 使用 iex -S mix
打开 iex
在用户 table 中插入了一条记录。
一个。 userChangeset = User.changeset(%User{}, %{email: "xyz@gmail.com", first_name: "xyz", last_name: "z"})
b. user1 = Repo.insert!(userChangeset)
在角色 table 中插入了一条记录。
一个。 roleChangeset = Role.changeset(%Role{}, %{code: "CON", description: "Consumer"})
b. role1 = Repo.insert!(roleChangeset)
- 现在一切正常,我在变量 user1 中有用户记录,在变量 role1 中有角色记录。
- 现在我需要关联这两个记录以在 UserRole Table 中插入一条记录。将在关联 user1 和 role1 记录时自动创建
通过在 iex
使用以下命令关联 user1 和 role1 记录
一个。 userRoleAssoc = user1 |> Repo.preload(:roles) |> Ecto.Changeset.change() |> Ecto.Changeset.put_assoc(:roles, [role1]) |> Repo.update !
是的,它在 UserRole 中插入一条记录,如下所示
- 但这里的问题是,我需要在关联时插入 status 字段。我该怎么做。
我尝试更新 UserRole 记录
一个。 fetchUserRole = Repo.get_by(UserRole, id: 1)
b。 fetchUserRole = %{ fetchUserRole |状态:"Active"}
c。 fetchUserRole |> Ecto.Changeset.change() |> Repo.update
它给出了以下结果。结果它得到了更新但没有反映在我的数据库中。结果与上图一样。
{:好的,
%用户角色{
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
}}
我的问题是,如果是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 在上面不起作用。
我是 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
// 以下是我完成的步骤
- 使用 iex -S mix 打开 iex
在用户 table 中插入了一条记录。
一个。 userChangeset = User.changeset(%User{}, %{email: "xyz@gmail.com", first_name: "xyz", last_name: "z"}) b. user1 = Repo.insert!(userChangeset)
在角色 table 中插入了一条记录。
一个。 roleChangeset = Role.changeset(%Role{}, %{code: "CON", description: "Consumer"}) b. role1 = Repo.insert!(roleChangeset)
- 现在一切正常,我在变量 user1 中有用户记录,在变量 role1 中有角色记录。
- 现在我需要关联这两个记录以在 UserRole Table 中插入一条记录。将在关联 user1 和 role1 记录时自动创建
通过在 iex
使用以下命令关联 user1 和 role1 记录一个。 userRoleAssoc = user1 |> Repo.preload(:roles) |> Ecto.Changeset.change() |> Ecto.Changeset.put_assoc(:roles, [role1]) |> Repo.update !
是的,它在 UserRole 中插入一条记录,如下所示
- 但这里的问题是,我需要在关联时插入 status 字段。我该怎么做。
我尝试更新 UserRole 记录
一个。 fetchUserRole = Repo.get_by(UserRole, id: 1)
b。 fetchUserRole = %{ fetchUserRole |状态:"Active"}
c。 fetchUserRole |> Ecto.Changeset.change() |> Repo.update
它给出了以下结果。结果它得到了更新但没有反映在我的数据库中。结果与上图一样。
{:好的, %用户角色{ 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 }}
我的问题是,如果是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 在上面不起作用。