Daniel Zanzini

Supposons que vous ayez un Appointment modèle et souhaitez enregistrer la date et l'heure de la planification. Étant donné que vous avez besoin de valeurs de date et d'heure, le choix évident est d'aller avec un seul datetime attribut nommé starts_at.

Maintenant, vous devez l'afficher de manière à ce que l'utilisateur puisse entrer cette valeur. Rails a un intégré datetime_select assistant. Il divise le datetime attribuer en cinq parties plus petites: année, mois, jour, heure et minute et crée un sélecteur pour chacune de ces parties.

Cela suffirait si nous voulions que nos utilisateurs sélectionnent cinq entrées différentes, mais la conception de notre application est différente, elle ne nécessite que deux entrées: une pour la date et une autre pour l'heure.

Nos entrées de date et d'heure

Cette conception nous a empêché d'utiliser la solution intégrée de Rails, nous avons donc décidé de créer deux attributs virtuels pour représenter la date et l'heure. Plongeons-nous dans cette solution.

Tout d'abord, vérifions notre point de vue avec ces deux entrées. Je vais sauter la partie sélecteur de date pour des raisons de clarté.

Notre nouvelle vue de rendez-vous utilisant deux attributs virtuels

Dans l'extrait ci-dessus, il y a deux attributs que nous devons définir: starts_at_time et starts_at_date. Nous le ferons dans le Appointment modèle en créant un getter et un setter pour chacun:

Notre modèle de rendez-vous avec des attributs virtuels définis

Si nous chargeons notre vue maintenant, elle devrait s'afficher correctement 🎉. Mais si vous essayez de créer le rendez-vous en utilisant la vue ci-dessus, vous verrez que les valeurs choisies pour starts_at_date et starts_at_time ne sont pas stockés dans starts_at. Cela se produit parce que nous avons encore besoin de cartographier la persistancestarts_at aux valeurs stockées dans les deux attributs virtuels. La façon la plus courante de procéder consiste à définir un before_save rappeler:

Notre modèle utilisant un rappel pour définir la valeur réelle de starts_at

Maintenant, nous l'avons fait. Nos entrées fonctionnent et nous sauvegardons la valeur correcte dans notre starts_at attribut. Nous pourrions nous arrêter ici, mais je n'aime pas beaucoup cette approche pour quelques raisons. Premièrement, cela peut créer des problèmes avec les validations. En plus de cela, nous avons pu voir un comportement inattendu sur d'autres parties du système en raison du rappel. Enfin, le starts_at l'attribut ne sera pas défini / écrasé tant que nous n'aurons pas enregistré le rendez-vous.

Pour cette raison, j'ai décidé d'aller avec une solution plus simple qui met à jour la valeur en starts_at chaque fois que nous définissons l'une des valeurs de starts_at_date ou starts_at_time:

Et c'est tout 🎉. Une solution simple et facile à gérer datetime champs à entrées multiples.