web-dev-qa-db-fra.com

Qu'est-ce qu'un changeset dans Phoenix Elixir

J'ai du mal à comprendre le changeset dans le modèle. Ce qu'il fait? Pouvons-nous avoir plus d'un ensemble de modifications dans un même modèle? par exemple. un pour créer et un autre pour mettre à jour.

Quelqu'un peut-il élaborer de manière simple afin d'aider d'autres personnes à venir à Phoenix?.

34
Murtza

De la documentation :

Les changesets permettent de filtrer, transtyper, valider et définir des contraintes lors de la manipulation de modèles.

Il existe un exemple de travail avec des ensembles de modifications dans la documentation d'introduction du module Ecto. Les fonctions change/2 et cast/4 sont les points d'entrée habituels pour créer des changesets, tandis que les fonctions restantes sont utiles pour les manipuler.

Les changesets sont utilisés pour créer et modifier vos modèles. Un changeset est littéralement une structure qui stocke un ensemble de changements (ainsi que les règles de validation.) Vous passez un changeset à votre Ecto Repo pour conserver les modifications si elles sont valides.

La branche maître actuelle d'Ecto supprime une conversion implicite lors du passage d'un modèle au référentiel lors de la mise à jour, ce qui signifie que l'utilisation d'un changeset est le seul moyen de mettre à jour un modèle.

Depuis le changelog:

Étant donné qu'un modèle de Repo.update/2 a été déconseillé car il est inefficace et sujet aux erreurs car les modifications ne peuvent pas être suivies

En termes de plusieurs ensembles de modifications par modèle, la réponse est certainement oui. Un changeset est simplement une fonction. En fait, vous n'avez même pas besoin de mettre les fonctions d'ensemble de modifications dans vos modèles, mais c'est un endroit commun pour les mettre.

Si vous avez besoin de plus de champs lors de l'enregistrement d'un utilisateur que de la mise à jour d'un utilisateur, vous pouvez définir unregister_changeset et un create_changeset avec différents champs obligatoires.

25
Gazler

Si vous êtes un peu familier avec Rails, ActiveRecord centralise l'accès à la base de données, la génération de requêtes et la validation dans vos modèles, Ecto divise ces responsabilités en modules séparés.

Les méthodes ActiveRecord sont exécutées dans la classe ou l'instance de modèle, tandis qu'Ecto s'attend à ce que vous passiez un modèle, une requête ou un ensemble de modifications à ses fonctions.

Ecto utilise l'ensemble de modifications pour effectuer des validations, plutôt que de traiter les validations à l'intérieur du modèle.

Les modifications Ecto fournissent à la fois des validations et des contraintes qui sont finalement transformées en erreurs en cas de problème.

La différence entre eux est que les validations peuvent être exécutées sans avoir besoin d'interagir avec la base de données et, par conséquent, sont toujours exécutées avant de tenter d'insérer ou de mettre à jour l'entrée dans la base de données.

Cependant, les contraintes ne peuvent être vérifiées de manière sûre que lors de l'exécution de l'opération dans la base de données. Par conséquent, les validations sont toujours vérifiées avant les contraintes. Les contraintes ne seront même pas vérifiées en cas d'échec des validations.

Voyons un exemple:

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

Dans le changeset/2 ci-dessus, nous définissons deux validations - une pour vérifier le format de l'e-mail et une autre pour vérifier l'âge - ainsi qu'une contrainte unique dans le champ e-mail.

Supposons que l'e-mail soit donné mais que l'âge n'est pas valide. L'ensemble de modifications contiendrait les erreurs suivantes:

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

Dans ce cas, nous n'avons pas vérifié la contrainte unique dans le champ e-mail car les données n'ont pas été validées. Fixons l'âge et supposons cependant que l'e-mail existe déjà dans la base de données:

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

Les validations et les contraintes définissent une limite explicite lorsque la vérification a lieu. En déplaçant les contraintes vers la base de données, nous fournissons également un moyen sûr, correct et sans course de données de vérifier les entrées de l'utilisateur.

vous pouvez trouver plus de détails ici Ecto Change Set

16
Subhash Chandra