Ruby Timecop - Comment ça marche ?
Hier je vous parlais de Timecop, une gem Ruby qui arrête le temps, très utile pour tester les dates. J’y ai repensé un peu aujourd’hui sur le mode : «j’aurais pu y penser avant !».
Alors justement, si j’avais eu cette idée, comment j’aurais
fait ? C’est l’occasion de parler de méta-programmation.
Allez j’essaye d’écrire ma propre méthode
Time.freeze
, on verra bien…
Voilà les étapes qui me semble nécessaires:
- Geler le temps et le retenir.
- Faire un backup de Time.now.
- Définir une nouvelle méthode Time.now qui renvoie toujours le même temps.
- Appeler le block passé à la méthode.
- Restaurer la méthode Time.now originale.
Avant de coder, j’écris un test:
Je veux donc obtenir un affichage du genre:
Time before hh:mm:00
hh:mm:03
hh:mm:03
Time after hh:mm:09
Ok ? C’est parti.
Ouvrir la classe Time
Premier truc à savoir, une classe Ruby est toujours ouverte à la modification. Même si il s’agit d’une classe du coeur du langage, comme Object ou Kernel. Si vous êtes perdus, faites une recherche sur «ruby open class».
Arrêter le temps
Pas grand chose à dire. On pourra renvoyer l’objet freezed
chaque fois qu’on nous demandera Time.now
.
Sauvegarder Time.now original
Là il y a beaucoup à dire. On rentre dans la méta-programmation et je n’ai pas la place (ni le temps) dans cet article pour parler du modêle objet de Ruby. N’hésitez pas à faire une recherche sur «ruby object model» ou «ruby eigenclass».
On dit à la classe Time
de créer un alias de la méthode de
classe now
avec le nom old_now
.
Un nouveau Time.now
Cette fois, je dis à la classe Time
de créer une méthode de
classe qui s’appelle now
et qui renvoie notre objet
freezed
.
Appeler le block
Bon, ça c’était facile ;)
Restaurer Time.now
Ça me semble tout bon. On teste ?
Le test
Excellent !
Il reste un léger problème : la méthode Time.old_now
existe toujours, ce qui n’est pas très propre. On pourra
la supprimer ainsi:
singleton_class.send(:remove_method, :old_now)
Voilà, j’aurais quand même pu y penser avant… J’espère trouver du temps une prochaine fois pour jeter un coup d’oeil au code de Timecop pour comparer avec le code d’aujourd’hui.
À demain.