我在理解changeset
in 模型时遇到问题。它能做什么?我们可以在一个模型中拥有多个变更集吗?例如,一个用于创建,另一个用于更新。
有人可以用简单的方式详细说明,以便帮助其他人来凤凰城。
我在理解changeset
in 模型时遇到问题。它能做什么?我们可以在一个模型中拥有多个变更集吗?例如,一个用于创建,另一个用于更新。
有人可以用简单的方式详细说明,以便帮助其他人来凤凰城。
从文档中:
变更集允许在操作模型时过滤、转换、验证和定义约束。
Ecto 模块的介绍性文档中有一个使用变更集的示例。函数 change/2 和 cast/4 是创建变更集的常用入口点,而其余函数对于操作它们很有用。
变更集用于创建和修改模型。变更集实际上是一个存储一组变更(以及验证规则)的结构。您将变更集传递给您的 Ecto Repo 以保留有效的变更。
Ecto 的当前主分支在更新时将模型传递给 Repo 时删除了隐式转换,这意味着使用变更集是更新模型的唯一方法。
从变更日志:
鉴于 Repo.update/2 的模型已被弃用,因为它无效且容易出错,因为无法跟踪更改
就每个模型有多个变更集而言,答案肯定是肯定的。变更集只是一个函数。实际上,您甚至不需要将变更集函数放入模型中,但这是放置它们的常见位置。
如果您在注册用户时需要比更新用户更多的字段,那么您可以使用不同的必填字段定义 aregister_changeset
和 a 。create_changeset
如果您对 Rails 有点熟悉,ActiveRecord 在您的模型中集中了数据库访问、查询生成和验证,Ecto 将这些职责划分为单独的模块。
ActiveRecord 方法在模型类或实例中执行,而 Ecto 期望您将模型、查询或变更集传递给它的函数。
Ecto 使用变更集来执行验证,而不是处理模型内部的验证。
Ecto 变更集提供验证和约束,万一出现问题,最终会变成错误。
它们之间的区别在于无需与数据库交互就可以执行验证,因此始终在尝试插入或更新数据库中的条目之前执行。
但是,只有在数据库中执行操作时才能以安全的方式检查约束。因此,总是在约束之前检查验证。如果验证失败,甚至不会检查约束。
让我们看一个例子:
defmodule User do
use Ecto.Schema
import Ecto.Changeset
schema "users" do
field :name
field :email
field :age, :integer
end
def changeset(user, params \\ :empty) do
user
|> cast(params, ~w(name email), ~w(age))
|> validate_format(:email, ~r/@/)
|> validate_inclusion(:age, 18..100)
|> unique_constraint(:email)
end
end
在上面的changeset/2
函数中,我们定义了两个验证 - 一个用于检查电子邮件格式,另一个用于检查年龄 - 以及电子邮件字段中的唯一约束。
假设给出了电子邮件,但年龄无效。变更集将有以下错误:
changeset = User.changeset(%User{}, %{age: 0, email: "mary@example.com"})
{:error, changeset} = Repo.insert(changeset)
changeset.errors #=> [age: "is invalid"]
在这种情况下,我们没有检查电子邮件字段中的唯一约束,因为数据没有验证。但是,让我们修正年龄并假设电子邮件已经存在于数据库中:
changeset = User.changeset(%User{}, %{age: 42, email: "mary@example.com"})
{:error, changeset} = Repo.insert(changeset)
changeset.errors #=> [email: "has already been taken"]
当检查发生时,验证和约束定义了一个明确的边界。通过将约束移至数据库,我们还提供了一种安全、正确且无数据竞争的方法来检查用户输入。
你,可以在这里找到更多细节Ecto Change Set