Les données sont une excellente chose, mais les mauvaises données peuvent être très très mauvaises. Heureusement, si vous êtes un programmeur Ruby on Rails, vous avez une belle API d’assistants de validation ActiveRecord à votre disposition.
Ce guide est une exploration des validations ActiveRecord courantes et moins courantes dans une application Ruby on Rails donnée. Utilisez-le pour aider à garder vos bases de données heureuses!
Pourquoi utiliser des validations ?
Pour vous assurer que seules les données valides sont enregistrées dans votre base de données. En plus de la validation côté client, les validations au niveau du modèle fournissent une couche de sécurité supplémentaire pour tous les champs de formulaire d’une application Ruby on Rails.
Vous pouvez fournir des validations dans une variété de niveaux, mais tous ont leurs forces et leurs faiblesses.
- Contraintes de base de données – Les contraintes uniques au niveau de la base de données ne permettent pas de champs ou de colonnes en double si vous en avez besoin. Cela peut aller beaucoup plus loin que l’unicité. c’est-à-dire les valeurs par défaut, les contraintes non nulles, les plages, etc…
- Validation côté client – Elles sont utiles visuellement et offrent une meilleure expérience utilisateur, mais sont souvent plus peu fiables. Je fournirais presque toujours un plan de sauvegarde en utilisant cette approche comme il se doit.
- Niveau du modèle (Rails) – De quoi nous parlons maintenant!
- Niveau de contrôleur (Rails) – Tentant à utiliser mais plus difficile à tester et à entretenir. C’est une convention / une bonne pratique pour garder vos contrôleurs aussi légers que possible.
Quand la validation se produit-elle réellement ?
Directement depuis la documentation ruby on rails:
Il existe deux types d’objets d’enregistrement actifs : ceux qui correspondent à une ligne dans votre base de données et ceux qui ne le font pas. Lorsque vous créez un nouvel objet, par exemple en utilisant la méthode
new
, cet objet n’appartient pas encore à la base de données. Une fois que vous appelezsave
sur cet objet, il sera enregistré dans la table de base de données appropriée. L’enregistrement actif utilise la méthode d’instancenew_record?
pour déterminer si un objet est déjà dans la base de données ou non.
La création d’une nouvelle classe d’enregistrement actif nous donne la possibilité d’utiliser une méthode new_record?
pour comprendre tout cela.
class Article < ApplicationRecordend
Ce faisant, nous pouvons frapper rails console
pour identifier le processus.
$ rails console>> article = Article.new(title: "My Article")=> #<Article id:nil title: "My Article", created_at: nil, updated_at: nil>>> article.new_record?=> true>> article.save=> true>> article.new_record?=> false
Appeler réellement save
est ce qui le valide dans la base de données et crée en coulisses les instructions SQL
nécessaires pour le faire. En conséquence, les validations sont généralement exécutées avant l’envoi complet des données à la base de données.
Les méthodes suivantes déclenchent des validations lors de l’utilisation :
-
create
create!
-
save
-
save!
update
update!
Les versions bang (par exemple
save!
) déclenche une exception si l’enregistrement n’est pas valide. Les versions non-bang ne le font pas:save
etupdate
renvoiefalse
, etcreate
renvoie simplement l’objet.
Les méthodes qui ignorent les validations
Utilisant l’une des méthodes suivantes ignoreront entièrement les validations. Utilisez avec prudence les données précieuses!
decrement!
decrement_counter
increment!
increment_counter
toggle!
touch
update_all
update_attribute
update_column
update_columns
update_counters
Validation helpers
What I love about Ruby on Rails is the bundled goodness you get for doing pretty hard things. Les aides à la validation sont l’une de ces choses qui me font me sentir au chaud et à l’aise lorsque je déploie une nouvelle application dans la nature. Cela fournit beaucoup de support pour une large gamme de données que vous collectez peut-être du côté client.
Chaque assistant accepte une option :on
et :message
. Ces options définissent quand la validation doit être exécutée et quel message doit être ajouté à une collection errors
en cas d’échec (vous pouvez les utiliser pour aider à injecter ce qui ne va pas dans vos vues afin que l’utilisateur sache quoi changer / modifier).
Il y a une tonne d’aides à la validation, voici quelques-unes de mes plus utilisées. Veuillez consulter le guide sur les validations d’enregistrements actifs pour plus de cas d’utilisation.
Confirmation
Utile pour valider lorsque deux champs de texte doivent avoir la même entrée. Pensez à une confirmation par e-mail par exemple.
class User < ApplicationRecord validates :email, confirmation: trueend
Maintenant, dans votre vue, vous pouvez avoir deux champs:
<%= text_field :user, :email %><%= text_field :user, :email_confirmation %>
Un point positif ici est que cette validation ne s’effectue que si l’option presence
est également définie sur true dans le modèle.
Ainsi, le modèle User
reçoit une mise à jour:
class User < ApplicationRecord validates :email, confirmation: true validates :email_confirmation, presence: true end
Exclusion
Si vous devez réserver des mots ou vous assurer qu’une entrée donnée est unique, utilisez exclusion
.
class Profile < ApplicationRecord validates :username, exclusion: { in: %w(username1 username2 username3), message: "%{value} has already been taken." }end
Remarquez comment j’ai utilisé :message
ici aussi. Ceci est fourni sur tous les assistants de validation.
Vous pouvez également utiliser inclusion
de la manière opposée. Voir les documents pour plus d’informations!
Format
Les chaînes de formatage sont parfois idéales pour votre application. Vous pouvez utiliser des expressions régulières dans les validations pour modifier ce que vous recherchez.
class Plan < ApplicationRecord validates :plan_type, format: { with: /\A+\z/, message: "Plans can only inlude letters"}end
Length
J’utilise celui-ci tout le temps pour mettre une contrainte sur la longueur des caractères d’un champ donné.
class User < ApplicationRecord validates :name, length: { minimum: 5 } # sets a minimum validates :bio, length: { maximum: 500 } # sets a maximum validates :handle, length: { in: 5..16 } # provide a rangeend
N’hésitez pas à personnaliser les messages avec :message
ici aussi. Les éléments suivants sont tous disponibles pour personnaliser le message.
wrong_length
too_long
too_short
Exemple
class User < ApplicationRecord validates :bio, length: { maximum: 800, too_long: "%{count} characters is the maximum." }end
Presence
C’est probablement l’aide la plus utilisée dans mon sac à outils. La présence vérifie que les champs ne sont pas vides.
class User < ApplicationRecord validates :name, :email, presence: trueend
Vous pouvez également tester l’existence d’une association sur les modèles
class Article < ApplicationRecord belongs_to :user validates :user, presence: true # looks for a user_id field on the articleend
Sur le modèle opposé, vous pouvez faire de même avec un catch appelé inverse_of
class User < ApplicationRecord has_many :articles, inverse_of: :userend
Unicité
Peut-être voulez-vous des noms d’utilisateur uniques sur votre application? L’unicité aide à cela.
class User < ApplicationRecord validates :username, uniqueness: true, { message: "Username already taken" }end
Cela recherche en fait la table User
pour les enregistrements existants afin de déterminer uniqueness
Vous pouvez aller plus loin et limiter le uniqueness
jusqu’à un scope
.
class User < ApplicationRecord validates :plan, uniqueness: { scope: :year, message: "can only update one per year"}end
Validations conditionnelles
Parfois, il suffit de valider dans des conditions données. Vous pouvez effectuer des conditions en utilisant une approche comme celle-ci.
class Purchase < ApplicationRecord validates :card_number, presence: true, if: :paid_with_card? def paid_with_card? payment_type == "card" endend
Besoin de regrouper plusieurs conditions? Vous pouvez le faire
class User < ApplicationRecord with_options if: :is_admin? do |admin| admin.validates :location, length: { minimum: 10 } admin.validates :job_title, presence: true endend
Méthodes personnalisées
Parfois, les aides ne suffisent pas et vous pourriez avoir besoin de quelque chose de plus personnalisé. Vous pouvez créer vos propres méthodes qui font des validations que vous roulez vous-même.
class Invoice < ApplicationRecord validate :active_subscriber, on: :create def active_customer errors.add(:customer_id, "is not active") unless subscriber.active? endend
Notez ici que je valide cette méthode en utilisant l’option :on
qui vous permet de déterminer où initialiser la validation. Dans ce cas, j’ai choisi :create
.
Vous pouvez également vous connecter à la collection errors
car je dois modifier les sorties côté client si vous en avez besoin. Nous n’avons pas le :message
sur les méthodes personnalisées dans ce cas. En savoir plus sur les erreurs.
Mots finaux
Espérons que les validations vous ont ouvert des idées pour rendre votre application plus contrainte (dans le bon sens). L’utilisation de Ruby on Rails et de toutes ses facettes permet d’entrer des données sécurisées dans n’importe quelle base de données de votre choix. Des jetons CSRF aux validations au niveau de la base de données, il existe d’innombrables façons d’améliorer votre application pour rester calme quant aux données entrant.
Prise éhontée!
Si vous avez aimé ce post, j’ai plus de vidéos sur YouTube et ici sur mon blog. Vous voulez plus de contenu comme celui-ci dans votre boîte de réception? Abonnez-vous à ma newsletter et recevez-la automatiquement.
Consultez mon cours
Want Vous voulez apprendre Ruby on Rails à partir de zéro? Découvrez mon prochain cours appelé Hello Rails.