【发布时间】:2019-11-16 08:58:09
【问题描述】:
在我的应用程序中,我有一种方法可以创建一个新的response。 response 与 player 和 match 都有 belongs_to 关系。
此外,player 和 match 都与 team 具有 belongs_to 关系。
看起来像这样:
当插入新的response 时,我想验证变更集中具有player_id 和match_id 外键的player 和match 属于同一个team。
目前我正在实现这一点,如下所示。首先,定义一个自定义验证来检查属于外键的记录:
def validate_match_player(changeset) do
player_team =
Player
|> Repo.get(get_field(changeset, :player_id))
|> Map.get(:team_id)
match_team =
Match
|> Repo.get(get_field(changeset, :match_id))
|> Map.get(:team_id)
cond do
match_team == player_team -> changeset
true -> changeset |> add_error(:player, "does not belong to the same team as the match")
end
end
并将验证用作变更集的一部分:
def changeset(model, params \\ %{}) do
model
|> cast(params, [:player_id, :match_id, :message])
|> validate_required([:player_id, :match_id, :message])
|> foreign_key_constraint(:match_id)
|> foreign_key_constraint(:player_id)
|> validate_match_player()
|> unique_constraint(
:player,
name: :responses_player_id_match_id_unique,
message: "already has an response for this match"
)
end
这很好用,但需要一些额外的 SQL 查询来查找相关记录,以便获取它们的 team_id 外键来比较它们。
有没有更好的方法来做到这一点,也许使用约束来避免额外的查询?
【问题讨论】:
-
AFAIK,约束不能访问其他表的数据。因此,要么在 SQL 中编写一个触发器,在不满足该条件时阻止编辑,要么像这样保留它。
标签: validation elixir ecto changeset