7 bonnes pratique avec ruby on rails
Ruby on Rails reste l’un des frameworks les plus efficaces pour livrer rapidement des produits web fiables. Mais sa vitesse de développement peut aussi devenir un piège si l’on néglige la structure du code, la performance ou l’observabilité. Dans cet article, vous trouverez 7 bonnes pratiques Ruby on Rails applicables en équipe, orientées qualité, maintenabilité et scalabilité, avec des exemples concrets.
1) Structurer l’application au-delà du MVC (Services, Queries, Form Objects)
Le MVC de Rails est un excellent point de départ, mais à mesure que le produit grandit, les contrôleurs et modèles peuvent devenir “obèses”. Une bonne pratique consiste à extraire la logique métier et les requêtes complexes dans des objets dédiés.
Quand extraire ?
- Logique métier réutilisée par plusieurs contrôleurs
- Enchaînements de règles (validation, calcul, transitions d’état)
- Requêtes SQL complexes ou coûteuses
- Orchestration impliquant plusieurs modèles
Exemple : Service Object
# app/services/orders/checkout.rb
module Orders
class Checkout
def initialize(order:, user:)
@order = order
@user = user
end
def call
ActiveRecord::Base.transaction do
@order.validate! # ou validations métier dédiées
@order.pay!
@order.confirm!
end
@order
end
end
end
Bénéfice SEO-technique indirect mais réel : une base de code plus saine réduit le risque de bugs en production (erreurs 5xx), ce qui impacte l’expérience et la qualité globale du site.
2) Optimiser l’accès à la base de données (N+1, index, scopes)
La performance Rails est souvent limitée par la base de données. Les bonnes pratiques autour d’ActiveRecord et PostgreSQL font la différence.
Chasser les N+1
- Utilisez
includes,preload,eager_loadselon le besoin - Surveillez les endpoints critiques (pages publiques, API)
# Mauvais : N+1
@orders = Order.all
@orders.each { |o| o.user.email }
# Bon
@orders = Order.includes(:user)
@orders.each { |o| o.user.email }
Indexer intelligemment
- Index sur les clés étrangères (
user_id,account_id) - Index composite pour les filtres fréquents
- Index partiels si une condition est dominante (ex.
WHERE archived_at IS NULL)
Encapsuler les requêtes
Créez des scopes lisibles, et isolez les requêtes complexes dans des objets “Query”.
class Order < ApplicationRecord
scope :paid, -> { where(status: "paid") }
scope :recent, -> { order(created_at: :desc) }
end
3) Sécuriser par défaut (auth, autorisations, secrets)
Rails fournit de bons mécanismes, mais la sécurité doit être une pratique continue.
Authentification et sessions
- Protégez toutes les actions sensibles avec
before_action :authenticate_user! - Activez les protections CSRF (par défaut en Rails)
- En API, préférez des tokens (JWT) avec rotation/expiration si adapté
Autorisations (RBAC)
- Centralisez les règles (Pundit ou CanCanCan)
- Testez les policies comme du code métier
Secrets et configuration
- Utilisez
Rails.credentialsou un gestionnaire de secrets (Vault, AWS Secrets Manager) - Ne versionnez jamais les fichiers secrets
- Séparez les variables par environnement
Checklist rapide : HTTPS partout, en-têtes de sécurité (CSP, HSTS), dépendances à jour, et audit régulier (bundler-audit).
4) Mettre en place une stratégie de tests réaliste (TDD, pyramide, factories)
Tester Rails ne se résume pas à “avoir des tests”. Il faut une stratégie qui couvre le risque réel : logique métier, régressions, endpoints critiques.
Une pyramide pragmatique
- Beaucoup de tests unitaires (services, models)
- Une couche de tests d’intégration (requests)
- Quelques E2E (Cypress/Playwright) sur les parcours clés
Exemple : test de request (RSpec)
RSpec.describe "GET /api/orders", type: :request do
it "retourne les commandes de l'utilisateur" do
user = create(:user)
create(:order, user: user)
get "/api/orders", headers: auth_headers(user)
expect(response).to have_http_status(:ok)
end
end
Ajoutez une CI/CD (GitHub Actions, Jenkins) avec :
- exécution des tests
- lint (RuboCop)
- contrôle de sécurité (bundler-audit)
- build Docker si applicable
5) Gérer les tâches asynchrones correctement (Sidekiq, idempotence)
Les jobs (emails, exports, webhooks, traitements) améliorent la réactivité, mais introduisent des risques : doublons, concurrence, files bloquées.
Bonnes pratiques Sidekiq
- Rendez les jobs idempotents (exécutables plusieurs fois sans effet de bord)
- Utilisez des verrous applicatifs si nécessaire (ex. Redis)
- Fixez des timeouts et des retries adaptés
- Surveillez les dead jobs et la latence de queue
class SyncCrmJob
include Sidekiq::Job
def perform(customer_id)
customer = Customer.find(customer_id)
return if customer.crm_synced_at.present? && customer.crm_synced_at > 5.minutes.ago
CrmClient.sync(customer)
customer.update!(crm_synced_at: Time.current)
end
end
Couplez Sidekiq avec Redis, et documentez le dimensionnement (concurrency, memory) selon votre charge.
6) Améliorer l’observabilité (logs structurés, métriques, traces)
Sans observabilité, les incidents se transforment en enquêtes longues. Rails doit exposer des signaux clairs : logs, métriques, traces.
Logs structurés
- Loggez en JSON en production
- Ajoutez des champs : request_id, user_id, account_id, durée
- Évitez de logguer des données sensibles
Instrumentation
- ActiveSupport::Notifications pour mesurer les requêtes et services
- APM (Datadog, New Relic) pour traces et erreurs
- Metrics (Prometheus) pour latence, taux d’erreur, saturation
Indicateurs utiles :
- p95/p99 de latence par endpoint
- taux de 5xx
- nombre de requêtes SQL par requête HTTP
- temps en DB vs temps applicatif
7) Déployer proprement (Docker, migrations, performance runtime)
Un déploiement Rails robuste vise la répétabilité et la sécurité : même artefact, même configuration, migration maîtrisée.
Conteneurisation (optionnelle mais fréquente)
- Docker multi-stage pour réduire l’image
- Précompilation des assets
- Variables d’environnement injectées au runtime
Migrations sans douleur
- Évitez les migrations bloquantes sur de grosses tables (index concurrent, backfill)
- Séparez “déployer le code” et “migrer les données” quand nécessaire
- Ajoutez des garde-fous (feature flags) pour les changements de schéma
Performance runtime
- Activez le cache (fragment cache, Russian doll caching)
- Utilisez
redispour cache et sessions si pertinent - Vérifiez la configuration Puma (workers/threads) selon CPU/RAM
- Activez des optimisations comme YJIT (Ruby récent) si compatible
Conclusion
Appliquer ces 7 bonnes pratiques Ruby on Rails, c’est investir dans un produit plus rapide, plus sûr et plus facile à faire évoluer : structure du code au-delà du MVC, maîtrise de la base PostgreSQL, sécurité par défaut, tests réalistes, jobs Sidekiq robustes, observabilité solide et déploiements reproductibles. Commencez par un audit sur un périmètre critique (un endpoint, un flux métier), puis généralisez progressivement à l’ensemble de l’application.
Partagez cet article si vous l'avez trouvé utile