Ecto.Changeset
Changesets allow filtering, casting and validation of model changes.
There is an example of working with changesets in the introductory
documentation in the Ecto
module.
The Ecto.Changeset struct
The fields are:
valid?
- Stores if the changeset is validrepo
- The repository applying the changeset (only set after a Repo function is called)model
- The changeset root modelparams
- The parameters as given on changeset creationchanges
- Thechanges
from parameters that were approved in castingerrors
- All errors from validationsvalidations
- All validations performed in the changesetrequired
- All required fields as a list of atomsoptional
- All optional fields as a list of atoms
Summary↑
add_error(changeset, key, error) | Adds an error to the changeset |
apply(arg1) | Applies the changeset changes to its model |
cast(val, model, required, optional \\ []) | Converts the given |
change(model, changes \\ %{}) | Generates a changeset to change the given |
delete_change(changeset, key) | Deletes a change with the given key |
fetch_change(arg1, key) | Fetches a change |
fetch_field(arg1, key) | Fetches the given field from changes or from the model |
get_change(arg1, key, default \\ nil) | Gets a change or returns default value |
get_field(arg1, key, default \\ nil) | Gets a field from changes or from the model |
put_change(changeset, key, value) | Puts a change on the given key with value |
update_change(changeset, key, function) | Updates a change |
validate_change(changeset, field, validator) | Validates the given |
validate_change(changeset, field, metadata, validator) | Stores the validation |
validate_exclusion(changeset, field, data) | Validates a change is not in the enumerable |
validate_format(changeset, field, format) | Validates a change has the given format |
validate_inclusion(changeset, field, data) | Validates a change is included in the enumerable |
validate_length(changeset, field, opts) | Validates a change is a string of the given length |
validate_unique(changeset, field, opts) | Validates |
Types ↑
t :: %Ecto.Changeset{valid?: boolean, repo: atom | nil, model: Ecto.Model.t | nil, params: %{String.t => term} | nil, changes: %{atom => term}, required: [atom], optional: [atom], errors: [{atom, atom | {atom, [term]}}], validations: [{atom, atom | {atom, [term]}}]}
Functions
Adds an error to the changeset.
Examples
add_error(changeset, :name, :invalid)
Applies the changeset changes to its model
Note this operation is automatically performed on Ecto.Repo.insert/2
and
Ecto.Repo.update/2
, however this function is provided for
debugging and testing purposes.
Examples
apply(changeset)
Specs:
- cast(%{binary => term} | %{atom => term} | nil, Ecto.Model.t, [String.t | atom], [String.t | atom]) :: t
Converts the given params
into a changeset for model
keeping only the set of required
and optional
keys.
This functions receives the params
and cast them according
to the schema information from model
. params
is a map of
string keys or a map with atom keys containing potentially
unsafe data.
During casting, all valid parameters will have their key name
converted to atoms and stored as a change in the changeset.
All other parameters that are not listed in required
or
optional
are ignored.
If casting of all fields is successful and all required fields are present either in the model or in the given params, the changeset is returned as valid.
No parameters
The params
argument can also be nil. In such cases, the
changeset is automatically marked as invalid, with an empty
changes map. This is useful to run the changeset through
all validation steps for introspection.
Examples
iex> changeset = cast(params, post, ~w(title), ~w())
iex> if changeset.valid? do
...> Repo.update(changeset)
...> end
Specs:
- change(Ecto.Model.t, %{atom => term}) :: t
Generates a changeset to change the given model
.
This function is useful for directly changing the model, without performing casting nor validation.
For this reason, changes
expect the keys to be atoms.
See cast/4
if you'd prefer to cast and validate external
parameters.
Examples
iex> changeset = change(post, title: "new title")
iex> Repo.update(changeset)
%Post{...}
Deletes a change with the given key.
Specs:
- fetch_change(t, atom) :: {:ok, term} | :error
Fetches a change.
Specs:
- fetch_field(t, atom) :: {:changes, term} | {:model, term} | :error
Fetches the given field from changes or from the model.
While fetch_change/2
only looks at the current changes
to retrieve a value, this function looks at the changes and
then falls back on the model, finally returning :error
if
no value is available.
Specs:
- get_change(t, atom, term) :: term
Gets a change or returns default value.
Specs:
- get_field(t, atom, term) :: term
Gets a field from changes or from the model.
While get_change/3
only looks at the current changes
to retrieve a value, this function looks at the changes and
then falls back on the model, finally returning default
if
no value is available.
Puts a change on the given key with value.
Updates a change.
The function
is invoked with the change value only if there
is a change for the given key
. Notice the value of the change
can still be nil (unless the field was marked as required on cast/4
).
Validates the given field
change.
It invokes the validator
function to perform the validation
only if a change for the given field
exists and the change
value is not nil. The function must a list of errors (empty
meaning no errors).
In case of at least one error, they will be stored in the
errors
field of the changeset and the valid?
flag will
be set to false.
Stores the validation metadata
and validates the given field
change.
Similar to validate_change/3
but stores the validation metadata
into the changeset validators. The validator metadata is often used
as a reflection mechanism, to automatically generate code based on
the available validations.
Validates a change is not in the enumerable.
Examples
validate_exclusion(changeset, :name, ~w(admin superadmin))
Validates a change has the given format.
Examples
validate_format(changeset, :email, ~r/@/)
Validates a change is included in the enumerable.
Examples
validate_inclusion(changeset, :gender, ["male", "female", "who cares?"])
validate_inclusion(changeset, :age, 0..99)
Validates a change is a string of the given length.
Examples
validate_length(changeset, :title, 3..100)
validate_length(changeset, :title, min: 3)
validate_length(changeset, :title, max: 100)
validate_length(changeset, :code, is: 9)
Validates field
's uniqueness on Repo
.
Examples
validate_unique(changeset, :email, on: Repo)
Options
:on
- the repository to perform the query on:downcase
- when true, downcase values when performing the uniqueness query
Case sensitivity
Unfortunately, different databases provide different guarantees
when it comes to case sensitive. For example, in MySQL, comparisons
are case insensitive. In Postgres, users can define case insensitive
column by using the :citext
type/extension.
Those facts make it hard for Ecto to guarantee if the unique
validation is case insensitive or not and therefore it does not
provide a :case_sensitive
option.
However this function does provide a :downcase
option that
guarantees values are downcased when doing the uniqueness check.
When you set this option, values are downcased regardless of the
database you are using.
Since the :downcase
option downcases the database values on the
fly, use it with care as it may affect performance. For example,
if you must use this option, you may want to set an index with the
downcased value. Using Ecto.Migration
syntax, one could write:
create index(:posts, ["lower(title)"])
Many times though, you don't even need to use the downcase option
at validate_unique/3
and instead you can explicitly downcase
values before inserting them into the database:
cast(params, model, ~w(email), ~w())
|> update_change(:email, &String.downcase/1)
|> validate_unique(:email, on: Repo)