什么是凤凰灵药的变化集

Mur*_*tza 35 elixir ecto phoenix-framework

我在理解changeset模型时遇到问题.它能做什么?我们可以在一个模型中拥有多个变更集吗?例如一个用于创建,另一个用于更新.

有人可以用简单的方式详细说明,这样可以帮助其他人来凤凰城.

Gaz*_*ler 25

文档:

更改集允许在操作模型时过滤,转换,验证和定义约束.

在Ecto模块的介绍性文档中有一个使用变更集的示例.函数change/2和cast/4是创建变更集的常用入口点,而其余函数对于操作它们非常有用.

变更集用于创建和修改模型.变更集实际上是一个存储一组更改(以及验证规则)的结构.您将变更集传递给Ecto Repo,以便在变更有效时保留更改.

当将模型传递给Repo on update时,Ecto的当前主分支会删除隐式转换,这意味着使用变更集是更新模型的唯一方法.

来自更改日志:

鉴于Repo.update/2的模型已被弃用,因为它无效并且容易出错,因为无法跟踪更改

就每个模型具有多个变更集而言,答案肯定是肯定的.变更集只是一个功能.实际上,您甚至不需要将变更集功能放在模型中,但这是放置它们的常见位置.

如果在注册用户时需要更多字段而不是更新用户,则可以使用不同的必填字段定义a register_changeset和a create_changeset.


Sub*_*dra 16

如果您对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
Run Code Online (Sandbox Code Playgroud)

changeset/2上面的函数中,我们定义了两个验证 - 一个用于检查电子邮件格式,另一个用于检查年龄 - 以及电子邮件字段中的唯一约束.

我们假设给出了电子邮件但年龄无效.变更集会出现以下错误:

changeset = User.changeset(%User{}, %{age: 0, email: "mary@example.com"})
{:error, changeset} = Repo.insert(changeset)
changeset.errors #=> [age: "is invalid"]
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我们没有检查电子邮件字段中的唯一约束,因为数据未验证.让我们确定年龄并假设电子邮件已存在于数据库中:

changeset = User.changeset(%User{}, %{age: 42, email: "mary@example.com"})
{:error, changeset} = Repo.insert(changeset)
changeset.errors #=> [email: "has already been taken"]
Run Code Online (Sandbox Code Playgroud)

验证和约束在检查发生时定义显式边界.通过将约束移动到数据库,我们还提供了一种安全,正确且无数据争用的检查用户输入的方法.

你可以在这里找到更多细节Ecto Change Set