简体   繁体   English

凤凰et剂中的变更集是什么

[英]What is a changeset in phoenix elixir

I'm having problem understanding the changeset in model. 我在理解模型中的changeset遇到问题。 What it does? 它能做什么? Can we have more than one changeset in a single model? 一个模型中可以有多个变更集吗? eg one for create and another for update. 例如,一个用于创建,另一个用于更新。

Can someone elaborate in a simple way so it helps other folks coming to Phoenix. 有人可以用一种简单的方式进行详细说明,从而帮助其他人来凤凰城吗?

From the documentation : 文档中

Changesets allow filtering, casting, validation and definition of constraints when manipulating models.. 变更集允许在处理模型时过滤,强制转换,验证和定义约束。

There is an example of working with changesets in the introductory documentation in the Ecto module. Ecto模块的入门文档中有一个使用变更集的示例。 The functions change/2 and cast/4 are the usual entry points for creating changesets, while the remaining functions are useful for manipulating them. 函数change / 2和cast / 4是创建变更集的常用入口点,而其余功能对于操作它们非常有用。

Changesets are used for creating and modifying your models. 变更集用于创建和修改模型。 A changeset is literally a struct that stores a set of changes (as well as the validation rules.) You pass a changeset to your Ecto Repo to persist the changes if they are valid. 从字面上看,变更集是一种存储一组变更 (以及验证规则)的结构。您可以将变更集传递给Ecto Repo,以便在变更有效时将其保留。

The current master branch of Ecto removes an implicit conversion when passing a model to the Repo on update, which means using a changeset the only way to update a model. 当将模型传递给更新时的仓库时,Ecto的当前master分支将删除隐式转换,这意味着使用变更集是更新模型的唯一方法。

From the changelog: 从变更日志:

Given a model to Repo.update/2 has been deprecated as it is inneffective and error prone since changes cannot be tracked 给定Repo.update / 2模型已被弃用,因为它无效且容易出错,因为无法跟踪更改

In terms of having multiple changesets per model, the answer is certainly yes. 就每个模型具有多个变更集而言,答案肯定是肯定的。 A changeset is simply a function. 变更集只是一个功能。 You actually don't even need to put the changeset functions in your models, however that is a common place to put them. 实际上,您甚至不需要在模型中放置变更集功能,但这是放置它们的常见地方。

If you require more fields when registering a user than you do updating a user then you can define a register_changeset and a create_changeset with different required fields. 如果在注册用户时需要比更新用户更多的字段,则可以定义带有不同必填字段的register_changesetcreate_changeset

If you are little bit familiar with Rails, ActiveRecord centralizes database access, query generation, and validation in your models, Ecto divides these responsibilities into separate modules. 如果您对Rails有点熟悉,ActiveRecord可在模型中集中数据库访问,查询生成和验证,Ecto可将这些职责划分为单独的模块。

ActiveRecord methods are executed within the model class or instance, while Ecto expects you to pass a model, query, or changeset to its functions. ActiveRecord方法在模型类或实例内执行,而Ecto希望您将模型,查询或变更集传递给其函数。

Ecto uses the changeset to perform validations, rather than deal with validations inside the model. Ecto使用变更集执行验证,而不是处理模型内部的验证。

Ecto changesets provide both validations and constraints which are ultimately turned into errors in case something goes wrong. Ecto变更集提供了验证和约束,一旦出现问题,最终将变成错误。

The difference between them is that validations can be executed without a need to interact with the database and, therefore, are always executed before attemping to insert or update the entry in the database. 它们之间的区别在于,可以在不需要与数据库交互的情况下执行验证,因此,验证总是在尝试在数据库中插入或更新条目之前执行。

However, constraints can only be checked in a safe way when performing the operation in the database. 但是,只有在数据库中执行操作时才能以安全的方式检查约束。 As a consequence, validations are always checked before constraints. 结果,总是在约束之前检查验证。 Constraints won't even be checked in case validations failed. 万一验证失败,甚至都不会检查约束。

Let's see an example: 让我们来看一个例子:

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

In the changeset/2 function above, we define two validations - one for checking the e-mail format and another to check the age - as well as a unique constraint in the email field. 在上面的changeset/2函数中,我们定义了两个验证(一个用于检查电子邮件格式,另一个用于检查年龄),以及电子邮件字段中的唯一约束。

Let's suppose the e-mail is given but the age is invalid. 假设给出了电子邮件,但年龄无效。 The changeset would have the following errors: 变更集将出现以下错误:

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

In this case, we haven't checked the unique constraint in the e-mail field because the data did not validate. 在这种情况下,我们没有检查电子邮件字段中的唯一约束,因为数据没有验证。 Let's fix the age and assume, however, that the e-mail already exists in the database: 让我们确定年龄并假设该电子邮件已存在于数据库中:

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

Validations and constraints define an explicit boundary when the check happens. 验证和约束条件在检查发生时定义了明确的边界。 By moving constraints to the database, we also provide a safe, correct and data-race free means of checking the user input. 通过将约束移至数据库,我们还提供了一种安全,正确且无数据争用的方法来检查用户输入。

you, can find more details here Ecto Change Set 您可以在此处找到更多详细信息Ecto Change Set

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM