Fonctionnalités de Rails 6 : nouveautés et pourquoi c'est important
Publié: 2022-03-11Comme la plupart des fans de Ruby on Rails le savent peut-être, Rails 6 arrive bientôt et apporte un certain nombre de fonctionnalités et de modifications très attendues. Le but de cet article est de vous familiariser avec les fonctionnalités clés qui ont été ajoutées à Rails 6 et de décrire comment elles peuvent aider à améliorer vos applications, économisant ainsi un temps de développement précieux.
Pour commencer, rappelez-vous que Rails 6 nécessite Ruby 2.5+ et des bases de données mises à niveau. Assurez-vous donc d'avoir un plan pour mettre à niveau vos systèmes en conséquence, au cas où vous ne l'auriez pas déjà fait.
Quelles sont donc ces nouvelles fonctionnalités ? Voici un bref récapitulatif des fonctionnalités clés de Rails 6 que vous utiliserez probablement à l'avenir :
Tests dans Rails 6
En tant que développeurs professionnels Ruby on Rails, nous visons à assurer une couverture maximale de notre code. Cependant, les tests deviennent une activité fastidieuse lorsque nos cas de test deviennent «lourds» et que nous devons attendre plusieurs minutes, voire des heures, juste pour que les cas de test soient exécutés.
Tests parallèles
Eh bien, Rails 6 a une réponse ici. Il a ajouté une méthode de parallelize
à ActiveSupport::TestCase
qui vous permet de paralléliser la suite de tests avec des processus fourchus.
Donc, ce que vous devez faire pour paralléliser les processus de vos tests est d'ajouter ceci à votre test_helper.rb
:
parallelize(workers: 2)
Alternativement, nous pouvons remplacer nos commandes précédemment utilisées pour exécuter des tests. Par exemple, bin/rails test OR bin/rspec spec
peut désormais être remplacé par PARALLEL_WORKERS=15 rails test OR PARALLEL_WORKERS=15 rspec spec
.
En conséquence, vous pouvez modifier les commandes pour exécuter les suites de tests sur différentes plates-formes CI telles que Travis, Gitlab, CircleCI et autres.
Il existe également des crochets lorsque chaque processus est créé/détruit, qui peuvent être utilisés comme suit :
class ActiveSupport::TestCase parallelize_setup do |worker| # setup databases end parallelize_teardown do |worker| # cleanup databases end parallelize(workers: :number_of_processors) end
Remarque : si vous souhaitez en savoir plus, vous pouvez consulter les guides Rails pour plus de détails.
Test de câble d'action
Puisque nous parlions de tests efficaces, comprenons également comment Action Cable, l'une des fonctionnalités les plus marquantes de Rails 5, s'est améliorée. Il est désormais possible de tester Action Cable à tous les niveaux : connexions , chaînes et diffusions .
Les tests de connexion visent à vérifier si les identifiants d'une connexion sont correctement attribués ou si toute demande de connexion inappropriée est rejetée :
class ApplicationCable::ConnectionTest < ActionCable::Connection::TestCase test "connects with params" do connect params: { user_id: 42 } OR cookies.signed[:user_id] = "42" connect assert_equal connection.user_id, "42" end test "rejects connection without params" do assert_reject_connection { connect } end end
Des tests de chaîne peuvent être écrits pour vérifier si les utilisateurs peuvent s'abonner à des chaînes et si la chaîne a un flux :
class ChatChannelTest < ActionCable::Channel::TestCase test "subscribes and stream for room" do # Simulate a subscription creation by calling `subscribe` subscribe room: "15" # You can access the Channel object via `subscription` in tests assert subscription.confirmed? assert_has_stream "chat_15" end end
La diffusion sur les chaînes peut être testée comme ceci :
# app/jobs/chat_relay_job.rb class ChatRelayJob < ApplicationJob def perform_later(room, message) ChatChannel.broadcast_to room, text: message end end # test/jobs/chat_relay_job_test.rb require 'test_helper' class ChatRelayJobTest < ActiveJob::TestCase include ActionCable::TestHelper test "broadcast message to room" do room = rooms(:all) assert_broadcast_on(ChatChannel.broadcasting_for(room), text: "Hi!") do ChatRelayJob.perform_now(room, "Hi!") end end end
Remarque : Plus de conseils sur la façon de tester peuvent être trouvés ici.
Insertion et insertion en bloc
À un moment donné, nous devons tous insérer plusieurs enregistrements en une seule fois et avons trouvé de nombreuses solutions de contournement pour le faire. Eh bien, Rails 6 est livré avec une nouvelle méthode prête à l'emploi : insert_all
, similaire à update_all
.
Il ne déclenchera aucun rappel et exécutera une seule requête SQL. Il existe une méthode supplémentaire upsert_all
qui vous permet d'utiliser l'opération upsert qui est exposée par de nombreuses bases de données modernes comme Postgres. Vous pouvez désormais réduire vos requêtes d'insertion et optimiser votre code. Dites également adieu aux gemmes précédemment utilisées comme activerecord-import
.
Une seule requête INSERT
SQL est préparée par ces méthodes et une seule instruction SQL est envoyée à la base de données, sans instancier le modèle ni appeler les rappels et validations Active Record. Il est également possible de définir des critères lorsqu'une clé primaire (index uniques ou contraintes uniques) est violée avec une option permettant d'ignorer ou d'exécuter des requêtes upsert.
Quelques exemples sont ci-dessous :
result = Article.insert_all( [ { id: 1, title: 'Handling 1M Requests Per Second', author: 'John', slug: '1m-req-per-second' }, #...snip... ], returning: %w[ id title ], unique_by: :index_articles_on_title_and_author ) result = Article.upsert_all( [ { id: 1, title: 'Handling 1M Requests Per Second', author: 'John', slug: '1m-req-per-second' }, { id: 1, .... }, # duplicate 'id' here { id: 2, .... }, { id: 3, .... }, # duplicate 'title' and 'author' here { id: 4, .... }, { id: 5, .... }, # duplicate 'slug' here { id: 6, .... } ] )
Les méthodes insert
, insert!
et upsert
sont des enveloppes autour de insert_all
, insert_all!
et upsert_all
, respectivement.
Remarque : Il existe un très bon article qui traite des requêtes en masse concernant différentes bases de données. Si vous avez besoin d'informations supplémentaires, assurez-vous de les consulter.
Basculer entre plusieurs bases de données
L'une des principales fonctionnalités que de nombreuses grandes applications apprécieront est celle-ci : Rails 6 a enfin ajouté la prise en charge de plusieurs bases de données pour votre application, intégrées et prêtes à l'emploi, prêtes à l'emploi !
Bien sûr, le choix de conception vous appartient toujours, que vous souhaitiez diviser votre application en plusieurs microservices ayant chacun une base de données distincte, ou emprunter une route monolithique, ou ajouter plusieurs répliques en lecture pour votre application.
Cependant, avoir la possibilité de le faire d'une manière aussi simple a le potentiel de gagner beaucoup de temps sur le front du développement.
Voici à quoi ressemblera votre nouveau fichier database.yml
:
development: primary: database: my_primary_db user: root primary_replica: database: my_primary_db user: ro_user replica: true animals: database: my_animals_db user: root animals_replica database: my_animals_db user: ro_user replica: true
Voici des façons intéressantes de spécifier comment basculer vers différentes bases de données :
class AnimalsModel < ApplicationRecord self.abstract_class = true connects_to database: { writing: :animals_primary, reading: :animals_replica } end class Dog < AnimalsModel # connected to both the animals_primary db for writing and the animals_replica for reading end
Voici la page officielle de GitHub, qui est également bien documentée. Personnellement, j'ai hâte d'avoir également des capacités de partitionnement de base de données dans les futures mises à jour de Rails (quelque chose comme ça).
Boîte aux lettres d'action
Une autre fonctionnalité intéressante de Rails 6 est l'ajout d'Action Mailbox, qui ajoute la possibilité d' acheminer les e-mails entrants vers le contrôleur comme des boîtes aux lettres pour le traitement dans Rails.
Action Mailbox propose des entrées pour Mailgun, Mandrill, Postmark et SendGrid. Vous pouvez également gérer les e-mails entrants directement via les entrées Exim, Postfix et Qmail intégrées. Maintenant, vous pouvez probablement imaginer les avantages potentiels sans entrer dans plus de détails. Il peut s'agir de traiter directement les e-mails d'un service d'assistance ou d'automatiser les tickets d'assistance. Rails 6 permet aux clients de répondre directement par e-mail, et bien plus encore. Vous avez la possibilité d'explorer cette fonctionnalité et de proposer une approche idéale pour votre application.

Voici un petit exemple pour comprendre comment utiliser Action Mailbox :
COMMENTS_REGEX = /^comment\+(.+)@example\.com/i # app/mailboxes/application_mailbox.rb class ApplicationMailbox < ActionMailbox::Base routing COMMENTS_REGEX => :comments end # app/mailboxes/comments_mailbox.rb class CommentsMailbox < ApplicationMailbox def process user = User.find_by(email: mail.from) post_uuid = COMMENTS_REGEX.match(mail.to)[1] post = Post.find_by(uuid: post_uuid) post.comments.create(user: user, content: mail.body) end end
Aussi, la nouvelle façon de configurer les emails est la suivante (en prenant l'exemple de Sendgrid) :
# config/environments/production.rb config.action_mailbox.ingress = :sendgrid
Utilisez rails credentials:edit
pour ajouter le mot de passe aux informations d'identification chiffrées de votre application sous action_mailbox.ingress_password
, où Action Mailbox le trouvera automatiquement :
action_mailbox: ingress_password: …
Configurez SendGrid Inbound Parse pour transférer les e-mails entrants vers /rails/action_mailbox/sendgrid/inbound_emails
avec le nom d'utilisateur actionmailbox
et le mot de passe que vous avez généré précédemment. Si votre application réside sur https://example.com
, vous devez configurer SendGrid avec l'URL suivante :
https://actionmailbox:[email protected]/rails/action_mailbox/sendgrid/i
Au cas où vous voudriez approfondir cela, Rails a déjà un guide à ce sujet ici.
Zeitwerk
Zeitwerk est le nouveau chargeur de code pour Ruby. Étant donné une structure de fichiers conventionnelle, Zeitwerk charge les classes et les modules de votre projet à la demande, ce qui signifie que vous n'avez pas besoin d'écrire des appels de requête pour vos propres fichiers. Pour l'activer dans Rails 6, vous pouvez procéder comme suit :
config.autoloader = :zeitwerk
Vous pouvez en savoir plus sur Zeitwerk ici.
Conseils d'optimisation
Vous craignez que certaines de vos requêtes prennent trop de temps à s'exécuter ? Eh bien, vous avez maintenant un moyen de définir également des délais d'attente pour vos requêtes.
L'instruction suivante déclenchera une exception StatementTimeout
si l'exécution de la requête prend plus de temps que la normale :
User.optimizer_hints("MAX_EXECUTION_TIME(5000)").all
Il est pris en charge par MySQL et vous devrez explorer si votre base de données le prend en charge.
Tronquer la base de données
Qu'en est-il des données d'ensemencement ? L'instruction suivante tronquera toutes vos tables de base de données et vous pourrez ensuite procéder à l'ensemencement de vos données :
rails db:truncate_all
Plus besoin de supprimer vos bases de données pour semer. Vous conviendrez probablement qu'il s'agit d'une solution élégante et rapide.
Texte d'action
Peut-être une autre caractéristique notable pour de nombreuses applications qui jouent avec les éditeurs WYSIWYG est l'ajout de la prise en charge native de l'éditeur Trix dans les applications Rails 6. Ce sera certainement une bonne mise à niveau/ajout pour de nombreux projets.
La plupart des éditeurs HTML WYSIWYG ont une portée énorme - l'implémentation de chaque navigateur a son propre ensemble de bogues et de bizarreries, et les développeurs JavaScript doivent résoudre les incohérences. Trix contourne ces incohérences en traitant le contenteditable
comme un périphérique d'E/S : lorsque l'entrée parvient à l'éditeur, Trix convertit cette entrée en une opération d'édition sur son modèle de document interne, puis restitue ce document dans l'éditeur. Cela donne à Trix un contrôle total sur ce qui se passe après chaque frappe.
Installation:
rails action_text:install # app/models/message.rb class Message < ApplicationRecord has_rich_text :content end
Vous pouvez explorer le texte d'action plus en détail dans la documentation officielle, ici.
Sécurité
Aucune mise à niveau sérieuse n'est complète sans quelques améliorations de sécurité. Rails 6 ne déçoit pas non plus sur le plan de la sécurité. La première mise à niveau de sécurité notable est l'ajout de la prise en charge de l' autorisation d'hôte .
L'autorisation d'hôte est un nouveau middleware qui protège contre les attaques de reconnexion DNS en autorisant explicitement les hôtes auxquels une demande peut être envoyée. Cela signifie que vous pouvez définir les hôtes qui peuvent accéder à vos applications.
Une autre mise à niveau de sécurité est destinée à contrecarrer les attaques qui tentent de copier la valeur signée/cryptée d'un cookie et de l'utiliser comme valeur d'un autre cookie. Pour ce faire, il stocke le nom du cookie dans le champ d'objectif qui est ensuite signé/crypté avec la valeur du cookie. Ensuite, côté serveur, nous vérifions les noms des cookies et supprimons tous les cookies attaqués. Activez action_dispatch.use_cookies_with_metadata
pour utiliser cette fonctionnalité, qui écrit des cookies avec les nouvelles métadonnées d'objectif et d'expiration intégrées.
Webpack comme bundler par défaut
Comme c'est le standard de facto avec de nombreux frameworks JavaScript modernes pour le développement frontal, Rails 6 a ajouté Webpack comme bundler JavaScript par défaut via le gem webpacker, remplaçant le pipeline Rails Asset. Il s'agit d'un ajout relativement simple, et nous n'entrerons pas dans les détails. Autant dire que Webpack apportera un certain soulagement aux développeurs front-end débordés.
Prévenir les conditions de course
Rails 6 a une nouvelle méthode qui est utilisée pour empêcher les conditions de concurrence SELECT/INSERT dans notre code (je suis sûr que de nombreux lecteurs ont eu le malheur de rencontrer des conditions de concurrence lors de la mise à l'échelle de leur projet). Voici le fil GitHub au cas où vous auriez besoin d'informations supplémentaires.
La table sous-jacente doit avoir les colonnes pertinentes définies avec des contraintes uniques. Bien que nous évitions la condition de concurrence entre SELECT → INSERT de #find_or_create_by
, nous avons en fait une autre condition de concurrence entre INSERT → SELECT, qui peut être déclenchée si un DELETE entre ces deux instructions est exécuté par un autre client. Mais, pour la plupart des applications, c'est une condition que nous sommes beaucoup moins susceptibles de rencontrer.
Identifiants dans Rails 6
Depuis l'époque de Rails 5.2, les informations d'identification ont été nommées une nouvelle "façon Rails" pour traiter les informations sensibles avec la promesse de se débarrasser une fois pour toutes des infâmes fichiers .env . Avec les informations d'identification, les clés chiffrées pour les services tiers peuvent être vérifiées directement dans le contrôle de source.
Jusqu'à présent, cependant, Rails utilisait le même fichier crypté pour tous les environnements, ce qui rendait la gestion de différentes clés en développement et en production un peu délicate, en particulier lorsqu'il s'agissait de gros projets et de code hérité.
Dans Rails 6, ce problème est finalement résolu avec la prise en charge des informations d'identification par environnement. Encore une fois, de plus amples détails peuvent être explorés sur le fil de discussion officiel GitHub.
Rails 6 est-il une bonne mise à jour ?
Oui, et en fait, Rails 6 pourrait être décrit comme une mise à jour majeure, même si peu de gens l'appelleraient un changeur de jeu. Depuis que Ruby on Rails existe depuis des années, peu de gens s'attendent à des changements révolutionnaires, mais sa sixième incarnation apporte beaucoup à la table.
Certaines fonctionnalités déployées dans Rails 6 semblent être des améliorations mineures, tandis que d'autres ont le potentiel de gagner beaucoup de temps de développement, d'améliorer la sécurité, la robustesse, etc. Conclusion : Rails est mature, de nombreux développeurs restent enthousiastes quant à son avenir, et avec la sortie de Rails 6, il s'est encore amélioré.
Bien sûr, cette liste des fonctionnalités de Rails 6 est incomplète et pour afficher l'ensemble complet des modifications, vous devez consulter le journal des modifications. De plus, il y a beaucoup de dépréciations que vous devriez considérer. Enfin, si vous insistez pour passer en revue chaque modification et vous mettre à jour, veuillez lire les notes de version complètes.