6

J'ai créé une fourchette de dépôt ecto pour étendre le module Ecto.Changeset avec la possibilité d'ajouter des avertissements au changeset. Je voulais avoir une add_warnings/4 fonction qui ajoute un avertissement à l'changeset comme une simple liste d'avertissements avec cette structure warnings: [{atom, {String.t, Keyword.t}}], similaire à errors. La différence entre le comportement de warnings et errors est que lorsqu'une erreur se produit, les données ne sont pas conservées, mais lorsqu'un avertissement se produit, les données sont conservées.Ecto Changeset ajouter des fonctionnalités pour les avertissements

Ecto.Changeset struct étendu avec les touches warnings et warningless?:

defstruct valid?: false, warningless?: false, data: nil, params: nil, changes: %{}, repo: nil, 
     errors: [], warnings: [], validations: [], required: [], prepare: [], 
     constraints: [], filters: %{}, action: nil, types: nil, 
     empty_values: @empty_values 

fonctions Ecto pour la coulée, la modification, params de traitement, etc. ajustés. Fonction add_warnings/4 ajouté:

@spec add_warning(t, atom, String.t, Keyword.t) :: t 
def add_warning(%{warnings: warnings} = changeset, key, message, keys \\ []) when is_binary(message) do 
    %{changeset | warnings: [{key, {message, keys}}|warnings], warningless?: false} 
end 

Le résultat est que je reçois changeset avec les touches attendues:

#Ecto.Changeset<action: nil, changes: %{}, data: #Company.Booking<>, errors: [], 
valid?: true, warnings: [], warningless?: true> 

Quand je fais un changement avec l'erreur et d'avertissement que je reçois:

#Ecto.Changeset<action: nil, 
changes: %{pickup_address: #Ecto.Changeset<action: :update, 
changes: %{street_name: nil}, data: #Company.Address<>, 
errors: [street_name: {"can't be blank", [validation: :required]}], 
valid?: false, 
warnings: [phone_number: {"This phone number is not common in Netherlands", 
    []}], warningless?: false>}, data: #Company.Booking<>, errors: [], 
valid?: false, warnings: [], warningless?: true> 

Ainsi, tout est comme prévu, en ce qui concerne les avertissements. Puis, quand je fais un changement avec un avertissement mais sans erreur, je reçois:

#Ecto.Changeset<action: nil, 
changes: %{pickup_address: #Ecto.Changeset<action: :update, 
changes: %{street_name: "sss"}, data: #Company.Address<>, errors: [], 
valid?: true, 
warnings: [phone_number: {"This phone number is not common in Netherlands", 
    []}], warningless?: false>}, data: #Company.Booking<>, errors: [], 
valid?: true, warnings: [], warningless?: true> 

Tout est comme prévu. Quand je ne fais pas de changements à la forme que je serais encore reçu un avertissement pour le numéro de téléphone, mais je reçois:

#Ecto.Changeset<action: nil, changes: %{}, data: #Company.Booking<>, errors: [], 
valid?: true, warnings: [], warningless?: true> 

Je suis un changeset sans aucun avertissement qu'il n'y a pas changes clé dans changeset car les données n'a pas changé.

La question est la suivante, comment implémenter la fonctionnalité des avertissements pour avoir toujours des avertissements dans le changeset, même si aucun changement n'a été fait?

+0

Vous ne montrez aucune fonction de changeset. Vraisemblablement, ce que vous voulez faire est d'utiliser ['Ecto.Changeset.get_field/3'] (https://hexdocs.pm/ecto/Ecto.Changeset.html#get_field/3) au lieu de [' Ecto.Changeset.get_change /3'](https://hexdocs.pm/ecto/Ecto.Changeset.html#get_change/3) lors de l'ajout d'un avertissement. Cependant, quel est le but de ceci? Si vous voulez conserver les données sur avertissement, vous perdrez le changeset et ne pourrez pas montrer un message à l'utilisateur. –

Répondre

0

Vous devriez envisager de préremplir les mises en garde au début de la fonction de chaque changeset vous créer - puisque vous ne pouvez pas utiliser là-bas plug vous pouvez venir écrire une macro qui va gérer cette logique pour vous, est __using__ conseillé, il serait donc assez facile de distinguer votre logique de la logique par défaut d'Ecto. Votre validation ne doit pas ajouter d'avertissement à la liste des avertissements, mais vous devez l'appliquer d'une autre manière - si le champ est correct, vous supprimerez les avertissements déjà existants de cette liste. De cette façon, vous serez sûr que votre changeset est bien quand il est warningless, car il a supprimé tous les avertissements de cette liste et il fonctionnerait parfaitement pour les changements vides dans changeset.