Phoenix 1.2 使用了 Ecto 2.0,其中一大主要的变化就是cast
这个函数。
defmodule User do
use Ecto.Schema
import Ecto.Changeset
schema "users" do
field :name
field :email
field :age, :integer
end
def changeset(user, params \\ %{}) do
user
|> cast(params, [:name, :email, :age])
|> validate_required([:name, :email])
|> validate_format(:email, ~r/@/)
|> validate_inclusion(:age, 18..100)
end
end
The changeset/2
function first invokes Ecto.Changeset.cast/3
with the struct, the parameters and a list of required and optional fields; this returns a changeset. The parameter is a map with binary keys and a value that will be cast based on the type defined on the schema.
Any parameter that was not explicitly listed in the required or optional fields list will be ignored. Furthermore, if a field is given as required but it is not in the parameter map nor in the struct, it will be marked with an error and the changeset is deemed invalid.
After casting, the changeset is given to many Ecto.Changeset.validate_*/2
functions that validate only the changed fields. In other words: if a field was not given as a parameter, it won’t be validated at all. For example, if the params map contain only the “name” and “email” keys, the “age” validation won’t run.
任何不在 cast 第二个参数列表里面的原子代表了 required 和 optional 字段,任何不在这个列表里的字段都会被忽略。所以如果一个字段是 required,但是不在 parameter map 或 struct 中的话,那么它会被标记为错误,并且 changeset 注定是非法的。
在casting之后,changeset 会传递给许多的 Ecto.Changeset.validate_*/2
函数,来验证「改变的字段」的合法性。也就是说,如果一个字段不属于给定的parameter,那么它不会被验证。举例说明,如果params这个map只包含“name”和“email”的key,那么对于“age”的验证不会进行。
** Validations and constraints **
Ecto changesets provide both validations and constraints which are ultimately turned into errors in case something goes wrong.
The difference between them is that validations can be executed without a need to interact with the database and, therefore, are always executed before attempting 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.
这里说一下 validations 和 constraints 的区别,validations 不用接触数据库就可以执行,但是 constraints 在对数据库进行操作时候才会执行。validations 的检查要放在 constraints 之前。model 文件的 constraints 和 migration 中的 constraints 限定同时使用,能够把数据库错误转换为 changeset 错误。