Article écrit par Nicolas C.
Rails 7.2, actuellement en bêta, est sur le point de voir le jour. Cette nouvelle version apporte son lot de nouveautés, de choix d’outils et de configurations qui laissent entrevoir la direction que l’équipe de Rails souhaite prendre pour la suite.
Essayons de passer en revue les changements les plus notables.
Une configuration par défaut optimisée
Dans Rails 7.2, le compilateur JIT (Just In Time) qui fait parti de l’implémentation Ruby officielle (CRuby) depuis Ruby 3.1 est maintenant activé par défaut si vous utilisez Ruby 3.3 ou plus.
La version minimum de Ruby requise par Rails 7.2 est maintenant la 3.1.
Pour ceux qui ne savent pas ce qu’est YJIT, c’est tout simplement une technologie d’optimisation de l’interpréteur qui lui permet, à la volée, de compiler des portions de code en code machine. Ce qui en résulte, c’est une amélioration notable des performances et plus précisément une baisse de la latence dans les réponses de 15 à 25% dans les différents tests.
Si vous utilisez donc Rails 7.2 et Ruby 3.3 pour votre application, ce sera un bénéfice net sans aucune intervention dans le code, que ce soit en terme de configuration ou de code applicatif. Cet ajout est complètement transparent.
Une autre modification a été apportée pour, une fois encore, améliorer la latence.
La valeur de la configuration du nombre de threads utilisés dans Puma est passée de 5 à 3. D’après les cas concrets d’applications utilisées à grande échelle en production, ce changement permet de réduire le temps passé par Ruby à attendre la libération du Global VM Lock (GVL) et donc de laisser l’interpréteur travailler plus souvent.
Pour ceux qui se demandent ce qu’est le GVL, voyez ça comme un cadenas qui s’ouvre et se ferme en fonction des opérations que doit traiter l’interpréteur. Si une opération est bloquante (cadenas fermé), alors l’interpréteur arrête son travail et attend qu’on lui rende la main.
Pour finir sur les optimisations, le Dockerfile généré par Rails lors de la création d’un projet inclus désormais jemalloc, une bibliothèque bas niveau qui permet aux projets qui l’utilisent d’éviter la trop grande fragmentation des données en mémoire et une meilleure gestion de la concurrence.
Concrètement, le résultat est une baisse importante de la consommation mémoire de votre application au fil du temps en production. Sans elle, les applications Rails ont tendance à devenir de plus en plus gourmandes en mémoire au fur et à mesure du temps et peuvent nécessiter d’être relancées pour libérer la mémoire.
Chez Ouidou, nous utilisons systématiquement jemalloc sur toutes nos apps depuis des années avec succès. Toutes ont bénéficié d’une amélioration de la gestion mémoire et donc une meilleure réactivité.
Une fois de plus, vous pouvez y aller les yeux fermés et utiliser jemalloc sur vos applications sans vous poser de questions.
Configuration pour conteneurs de développement
L’utilisation de Docker et des conteneurs est devenue omniprésente dans le monde du développement.
Son utilisation permet de simplifier l’entrée (ou le démarrage) sur un projet en proposant une version packagée du projet et de toutes ses dépendances à travers l’utilisation d’une commande unique.
Depuis Rails 7.2, on peut obtenir la configuration pour ces dev containers à la génération du projet.
Il est bien sûr possible de modifier les fichiers générés (Dockerfile, docker-compose.yml, devcontainer.json) pour l’ajuster à ses besoins spécifiques mais avec la configuration par défaut, toute la stack classique sera déjà fonctionnelle.
Vous aurez donc :
- Redis
- une base de données (SQLite, Postgres, MySQL, MariaDB en fonction de votre choix lors du
rails new
) - Chrome headless pour les tests E2E
- tout le nécessaire pour faire tourner les briques spécifiques de Rails (ActiveStorage, ActionCable, …)
Nouveautés liées aux bases de données
Gestion des jobs dans les transactions
Lorsque vous utilisez les transactions ActiveRecord pour vous assurer que plusieurs opérations en base de données soient traitées d’un bloc et rollback si une erreur survient, vous avez également parfois besoin de lancer des tâches de fond avec Active Job.
Jusqu’à maintenant il n’y avait aucune garantie sur le fait de ne pas lancer la tâche de fond en cas de rollback.
On pouvait donc se retrouver avec des jobs lancés alors que l’opération principale n’avait pas aboutie.
À partir de Rails 7.2, les jobs ne seront mis en queue uniquement lorsque la transaction aura aboutie :
Topic.transaction do
topic = Topic.create
NewTopicNotificationJob.perform_later(topic)
end
Ça assure donc de ne pas se retrouver avec des jobs orphelins.
Cette fonctionnalité peut être désactivée à volonté si vos besoins nécessitent de déclencher le job quoi qu’il en soit.
Cette modification marque aussi la préparation du terrain pour l’arrivée de solidqueue dans Rails 8. Solidqueue est une nouvelle brique de Rails qui permet de gérer un système de queue directement en base de données. On pourra donc s’en servir pour des jobs classiques, des jobs à retardement, contrôler la concurrence, les tâches récurrentes, mettre en pause des queues, etc.
On pourra donc facilement se passer de Sidekiq par exemple.
Gestion des callbacks dans les transactions
Dans la même veine, avec Rails 7.2, les callbacks pourront être enregistrés dans les transactions.
Disons que vous voulez vous assurer qu’un callback after_commit
ne soit joué que si la transaction aboutie, vous pourrez le faire de la façon suivante :
Article.transaction do |transaction|
article.update(published: true)
transaction.after_commit do
# quelque chose à faire après le commit, envoyer un mail par exemple
end
end
Outils de qualité
Brakeman est désormais intégré par défaut dans les nouvelles applications générées à partir de Rails 7.2. Cette gem, si vous ne la connaissez pas, permet de scanner votre code applicatif pour y détecter d’éventuelles failles de sécurité, vous donnez leur niveau de sévérité et vous expliquer quel est le type de faille.
C’est donc un outil d’une aide précieuse pendant la phase de développement et qui peut être couplé à votre CI pour être joué à chaque push pour éventuellement bloquer le merge de pull requests problématiques.
Sachez que si vous travaillez sur Github, la nouvelle version de Rails met également à disposition un GitHub CI Workflow qui inclue notamment l’exécution de Brakeman.
Pour finir sur ce sujet, je pense que Brakeman a sa place dans chaque projet. Les faux positifs ne sont pas exclus comme dans tous les outils d’analyse statique mais beaucoup de remontées sont pertinentes. Pour les faux positifs, vous pourrez toujours les ignorer.
Rubocop a également été ajouté à la stack par défaut et se repose sur les régles de rubocop-rails-omakase.
On peut se questionner sur le choix de omakase qui se cale sur les préférences des core dev de Rails. Ces règles ne sont pas figées et vous pouvez les modifier à votre convenance.
Je ne suis, par exemple, pas fan d’indenter les méthodes qui sont sous le mot clé private
.
D’un point de vue personnel, je préfère un linter avec des valeurs fortes, un vrai standard. Je pense naturellement à standardrb qui lui se positionne comme un linter avec des opinions fortes sans laisser place à la configuration mais qui est utilisé et validé par une grande partie de la communauté et des développeurs de gems.
Ce choix évite aux équipes de devoir tous les mois revoir les règles en place sur chaque projet et de consulter les nouvelles pour savoir il faut les activer ou non et avec quelles options.
Autre
PWA
Rails génère maintenant les fichiers par défaut utilisés par les PWA (Progressive Web App) pour gérer le manifest et les service workers que vous trouverez dans app/views/pwa
.
Ces fichiers permettent d’indiquer à votre navigateur, que ce soit sur votre ordinateur ou votre téléphone, que votre application web peut-être installée comme application “native”, ce qui permet de l’avoir dans votre dock avec sa propre icône, avoir un fonctionnement hors-ligne, en tâche de fond. Bref elle permet de se rapprocher du comportement d’une application native.
Browser version guard
Rails 7.2 permet désormais de spécifier les versions des navigateurs que votre application supporte. On peut spécifier ces restrictions au niveau global de l’application, par contrôleur ou encore par action.
On pourra par exemple ajouter allow_browser versions: :modern
pour n’accepter que les navigateurs supportant les fonctionnalités modernes comme webp, web push, import maps, etc.
On pourra également être plus spécifiques en donnant des noms et versions minimum de navigateurs : allow_browser versions: { safari: 16.4, firefox: 121, ie: false }
Les navigateurs qui ne sont pas supportés seront redirigés vers une page spécifique avec un statut HTTP 406.
J’imagine que cette fonctionnalité peut être intéressante pour des applications qui nécessitent obligatoirement certaines fonctionnalités mais dans la majorité des cas, elle me semble agressive. Je préfère, en ce qui me concerne, mettre en place de solutions de replis autant que possible.
Puma-dev
Puma-dev est une solution élégante, pour ceux qui n’utilisent pas Docker, qui permet de lancer facilement plusieurs instances d’applications Rails en mode développement.
L’outil est facile à installer, démarre automatiquement vos apps au besoin, les coupe si elles ne sont pas utilisées. Un domaine (.puma
par exemple) sera disponible localement pour accéder à vos apps.
L’outil supporte en plus le HTTPS.
Rate limit
Rails 7.2 ajoute la possibilité de gérer du rate limit
dans ActionController
.
Cette fonctionnalité permet aux développeurs de contrôler la fréquence d’accès à des actions données.
rack-attack permettait déjà de gérer cette même problématique mais c’est désormais une brique spécifique incluse directement dans Rails.
On peut donc faire quelque chose comme :
class SessionsController < ApplicationController
rate_limit to: 10, within: 3.minutes, only: :create
end
ce qui limite à une adresse IP unique le nombre de requêtes à 10 dans un intervalle de 3 minutes. Au delà de ça, les requêtes seront refusées avec un code HTTP 429 Too Many Requests response
.
class SignupsController < ApplicationController
rate_limit to: 1000, within: 10.seconds, store: cache_store,
by: -> { request.domain },
with: -> { redirect_to busy_controller_url, alert: "Too many signups!" },
only: :new
end
Dans cet exemple on limite à 1000 requêtes dans un intervalle de 10 secondes. On utilise le cache_store
et on se base sur le domaine de la requête comme critère de regroupement. Si la limite est atteinte, on redirige vers une adresse spécifique avec un message d’alerte.
Amélioration des logs SQL
Rails 7.2 pourra vous aider un peu plus concernant le nombre de requêtes SQL effectuées par chaque action ce qui peut simplifier la détection d’actions complexes. La lecture des logs s’en trouve donc simplifiée.
L’avenir
Rails 7.2 nous apporte donc quelques belles nouveautés et améliorations comme l’utilisation plus intensive des conteneurs, le YJIT et jemalloc par défaut et le renforcement de la chaîne de développement et CI.
On voit aussi arriver quelques changements qui éclairent sur la vision pour Rails 8. J’attends avec encore plus d’impatience cette version 8 qui devrait nous apporter de très belles nouveautés.
En attendant qu’elle arrive, et ce n’est pas pour tout de suite, apprenons déjà à profiter des nouveaux outils fournis pas Rails 7.2.
Bon amusement !
À lire aussi

Ouicommit – L’intelligence artificielle en entreprise, on y est !

Hackathon Women in Tech : un engagement pour une tech plus inclusive

Les nouveautés Atlassian en 2025
