gpt4 book ai didi

elixir - 使用 Ecto 正确设置检查约束

转载 作者:行者123 更新时间:2023-12-04 13:41:04 26 4
gpt4 key购买 nike

我的模型中有这个 check_constraint 。

  def changeset(struct, params \\ %{}) do
struct
|> cast(params, @all_fields)
|> validate_required(@required_fields)
|> check_constraint(:stars, name: :stars_range, message: "stars must be between 1 and 5")
end

创建约束已成功迁移。
create constraint("reviews", "stars_range", check: "stars>=1 and stars<=5")

但是当我运行这个测试时,变更集是否有效?我希望它是无效的,因为我将整数 7 传递给 stars柱子。其约束为 1 through 5 .有人知道这里有什么问题吗?
test "requires stars to be within range of 1-5" do
user = insert(:user)
project = insert(:project, owner: user)
user_project_map = %{project_id: project.id, user_id: user.id}
review_map = Map.merge(@valid_attrs, user_project_map)

attrs = %{review_map | stars: 7}
changeset = Review.changeset(%Review{}, attrs)
refute changeset.valid?
end

最佳答案

引自 docs :

(...) Now, when invoking Repo.insert/2 or Repo.update/2, if the price is not positive, it will be converted into an error and {:error, changeset} returned by the repository. Note that the error will occur only after hitting the database so it will not be visible until all other validations pass.



这意味着 check_constraint仅当查询命中数据库时才会发生。因此您的 changeset.valid?返回 true在实际调用数据库之前检查验证时。您创建的约束是在数据库内部创建的,因此 Ecto 在调用它之前实际上无法知道该约束实际检查的内容。通常此类约束用于更复杂的检查,或者如果您的数据库中已经定义了约束(可能是因为您从另一个系统迁移了数据库?)。如果你想看到你的约束在行动,你应该在你的测试中写:

attrs = %{review_map | stars: 7}
changeset = Review.changeset(attrs)
{:error, changeset} = Repo.insert(changeset)
refute changeset.valid?

如果您需要 Changeset在调用数据库之前检查一些条件然后你应该使用像 validate_inclusion/4 这样的函数或 validate_subset/4 .您甚至可以使用 validate_change/4 编写自己的检查器(如果您需要更多解释如何操作,请告诉我)。如果您使用这些验证器,那么您的变更集将在调用数据库之前工作。

关于elixir - 使用 Ecto 正确设置检查约束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56971771/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com