Petite découverte de la semaine en Ruby On Rails et les dirty attributes.
Peut-être savez-vous déjà que, par exemple, dans un modèle avec un callback du type before_save
vous pouvez accéder aux modifications des attributs de l’instance du modèle avec changes
qui vous retourne un Hash
avec l’attribut comme clé et la valeur précédente et la nouvelle valeur?
1
person.changes # => { 'name' => ['bill', 'bob'] }
Peut-être savez-vous aussi qu’une méthode du type <nom de l'attribut>_changed?
existe pour chacun des attributs de votre modèle?
1
2
person.name_changed? # => true
person.age_changed? # => false
Mais savez-vous comment détecter si un attribut change d’une valeur précise vers une autre?
Disons que vous avez un modèle User
qui possède un champs authentication_method
, de type :integer
qui contient le mode d’authentification de ce dernier.
Disons aussi que l’une des méthodes d’authentifications demande à ce que des données soient mise à jour si l’utilisateur change sa méthode d’authentification, par exemple une méthode qui enregistre une clé USB, mais si l’utilisateur change le mode d’authentification, ses clés doivent être effacés.
Prenons la constante suivante:
1
AUTHENTICATION_METHODS = %w[no_method ga_authenticator fido_u2f].freeze
Comment faire pour détecter que authentication_method
change de la valeur 2
(position de fido_u2f
dans la constante AUTHENTICATION_METHODS
) vers une autre valeur?
Voici ce que j’ai trouvé dans la documentation des dirty attributes de Rails:
1
2
3
4
5
6
7
8
9
10
11
12
13
class User
AUTHENTICATION_METHODS = %w[no_method ga_authenticator fido_u2f].freeze
before_update :destroy_u2f_keys_if_removing_fido_authentification_method
private
def destroy_u2f_keys_if_removing_fido_authentification_method
return unless authentication_method_changed?(from: fido_u2f_method)
fido_usf_devices.destroy_all
end
end
Donc la méthode <nom de l'attribut>_changed?
peut recevoir les paramètres :from
et :to
, ici je n’utilise que le paramètre :from
puisque seule la valeur précédente m’intéresse ici.
Belle surprise 😀