ecto - 在多对多关系的中间 table 中设置字段
ecto - set field in intermediate table in many to many relationship
我有两个具有多对多关系的实体 Users 和 Rooms。
我在中间 table
添加了一个附加字段 permission
迁移:
def change do
create table(:room_users) do
add :permission, :string
add :user_id, references(:users)
add :room_id, references(:rooms)
end
create unique_index(:room_users, [:user_id, :room_id])
end
模式:
schema "rooms" do
field :name, :string
many_to_many :users, User, join_through: "room_users"
timestamps()
end
...
schema "users" do
field :username, :string
many_to_many :rooms, Room, join_through: "room_users"
timestamps()
end
我编写了一个将用户与房间相关联的变更集,它有效
def changeset_update_user(room, user) do
room
|> cast(%{}, [:name])
|> validate_required([:name])
|> put_assoc(:users, [user])
end
现在的问题是:每当我将用户关联到房间时,我也想设置权限字段。
像
def changeset_update_user(room, user) do
room
|> cast(%{}, [:name])
|> validate_required([:name])
|> put_assoc(:users, [%{user_id: user.id, permission: "HOST"}])
end
编辑:将用户与房间相关联的函数
def create_Room_with_User(attrs \ %{}, user) do
{result, room_dto} = %Room{}
|> Room.changeset(attrs)
|> Repo.insert()
Repo.preload(room_dto, :users)
|> Room.changeset_update_user(user)
|> Repo.update()
{result, room_dto}
end
但随后我得到一个错误,提示 user_id 和权限是未知字段
您得到的是 unknown field :permission
,因为这不是 User
字段,而是 RoomUser
字段。
如文档中所述,当您不需要关心中间 table 时,many_to_many/3
是一种便利:因为您需要 permission
,所以情况并非如此.
引用文档:
If you need to access the join table, then you likely want to use has_many/3
with the :through option instead.
想法描述here。
在你的例子中翻译成:
defmdoule Room do
use Ecto.Schema
schema "rooms" do
field :name, :string
has_many :room_users, RoomUser
has_many :users, through: [:room_users, :user]
end
end
defmodule User do
use Ecto.Schema
schema "users" do
field :name, :string
has_many :room_users, RoomUser
has_many :rooms, through: [:room_users, :room]
end
end
defmodule RoomUser do
use Ecto.Schema
schema "room_users" do
field :permission, :string
belongs_to :user, User
belongs_to :room, Room
end
end
然后您可以将 put_assoc
替换为:
|> put_assoc(:room_users, [%{user: user, permission: "HOST"}])
我有两个具有多对多关系的实体 Users 和 Rooms。
我在中间 table
添加了一个附加字段permission
迁移:
def change do
create table(:room_users) do
add :permission, :string
add :user_id, references(:users)
add :room_id, references(:rooms)
end
create unique_index(:room_users, [:user_id, :room_id])
end
模式:
schema "rooms" do
field :name, :string
many_to_many :users, User, join_through: "room_users"
timestamps()
end
...
schema "users" do
field :username, :string
many_to_many :rooms, Room, join_through: "room_users"
timestamps()
end
我编写了一个将用户与房间相关联的变更集,它有效
def changeset_update_user(room, user) do
room
|> cast(%{}, [:name])
|> validate_required([:name])
|> put_assoc(:users, [user])
end
现在的问题是:每当我将用户关联到房间时,我也想设置权限字段。 像
def changeset_update_user(room, user) do
room
|> cast(%{}, [:name])
|> validate_required([:name])
|> put_assoc(:users, [%{user_id: user.id, permission: "HOST"}])
end
编辑:将用户与房间相关联的函数
def create_Room_with_User(attrs \ %{}, user) do
{result, room_dto} = %Room{}
|> Room.changeset(attrs)
|> Repo.insert()
Repo.preload(room_dto, :users)
|> Room.changeset_update_user(user)
|> Repo.update()
{result, room_dto}
end
但随后我得到一个错误,提示 user_id 和权限是未知字段
您得到的是 unknown field :permission
,因为这不是 User
字段,而是 RoomUser
字段。
如文档中所述,当您不需要关心中间 table 时,many_to_many/3
是一种便利:因为您需要 permission
,所以情况并非如此.
引用文档:
If you need to access the join table, then you likely want to use
has_many/3
with the :through option instead.
想法描述here。
在你的例子中翻译成:
defmdoule Room do
use Ecto.Schema
schema "rooms" do
field :name, :string
has_many :room_users, RoomUser
has_many :users, through: [:room_users, :user]
end
end
defmodule User do
use Ecto.Schema
schema "users" do
field :name, :string
has_many :room_users, RoomUser
has_many :rooms, through: [:room_users, :room]
end
end
defmodule RoomUser do
use Ecto.Schema
schema "room_users" do
field :permission, :string
belongs_to :user, User
belongs_to :room, Room
end
end
然后您可以将 put_assoc
替换为:
|> put_assoc(:room_users, [%{user: user, permission: "HOST"}])