• Contenu
  • Bas de page
logo ouidoulogo ouidoulogo ouidoulogo ouidou
  • Qui sommes-nous ?
  • Offres
    • 💻 Applications métier
    • 🤝 Collaboration des équipes
    • 🛡️ Sécurisation et optimisation du système d’information
    • 🔗 Transformation numérique
  • Expertises
    • 🖥️ Développement logiciel
    • ♾️ DevSecOps
    • ⚙️ Intégration de logiciels et négoce de licences
      • Atlassian : Jira, Confluence, Bitbucket…
      • Plateforme monday.com
      • GitLab
      • SonarQube
    • 📚​ Logiciel de CRM et de gestion
    • 🎨 UX/UI design
    • 🌐 Accessibilité Numérique
    • 🗂️​ Démarches simplifiées
    • 📝 Formations Atlassian
  • Références
  • Carrières
    • 🧐 Pourquoi rejoindre Ouidou ?
    • ✍🏻 Nous rejoindre
    • 👨‍💻 Rencontrer nos collaborateurs
    • 🚀 Grandir chez Ouidou
  • RSE
  • Ressources
    • 🗞️ Actualités
    • 🔍 Articles techniques
    • 📖 Livres blancs
    • 🎙️ Interviews Clients
Nous contacter
✕
Premier pas sur Wayland
Premier pas sur Wayland
24 septembre 2021
Google Maps API Places Autocomplete en Typescript via Angular
Google Maps API Places Autocomplete en Typescript via Angular
12 octobre 2021
Ressources > Articles techniques > Configuration applicative

Configuration applicative

Article écrit par François Vantomme

Lorsqu’il s’agit de configurer une application Rails, chez Ouidou Nord, nous aimons bien y apporter une grande souplesse pour pouvoir nous adapter à de multiples situations. C’est pourquoi on favorise l’usage de variables d’environnement. Pour accéder à ces variables, on pourra utiliser ENV.fetch("ma_variable") si sa présence est obligatoire, ou ENV["ma_variable"] si elle est optionnelle.

Se pose alors la question des variables booléennes. Par convention, nous avons choisi de favoriser «0» ou «1» au détriment d’autres valeurs comme «true», «FALSE», «yes», «f», etc. Ainsi, une variable d’environnement booléenne sera récupérée via ENV.fetch("ma_variable").to_i.positive?.

Fail fast

The most annoying aspect of software development, for me, is debugging. I don’t mind the kinds of bugs that yield to a few minutes’ inspection. The bugs I hate are the ones that show up only after hours of successful operation, under unusual circumstances, or whose stack traces lead to dead ends. Fortunately, there’s a simple technique that will dramatically reduce the number of these bugs in your software. It won’t reduce the overall number of bugs, at least not at first, but it’ll make most defects much easier to find. The technique is to build your software to “fail fast.”

— Jim Shore

Dans l’idéal, quel que soit le framework ou le langage, il est préférable de récupérer l’ensemble des variables d’environnement utiles à l’application au démarrage de celle-ci, de manière centralisée, pour faciliter la prise de connaissance de ces variables et leur mise à jour. Ainsi, si une variable est manquante au démarrage, on pourra faire planter l’application dès son lancement avec un message explicite. Ceci évite d’avoir des plantages aléatoires à l’exécution ; à l’envoi d’un courriel ou lors d’un appel à une API par exemple.

Configuration X

Dans le cas d’une application Rails, on va centraliser la récupération des variables d’environnement dans le fichier config/application.rb. On a donc notre point centralisé, chargé au démarrage de l’application qui va nous permettre d’être robuste face aux variables d’environnement manquantes.

Rails prévoit un mécanisme pour stocker toutes les informations de configuration transversales à l’application. Cela nous évite de passer par un système maison, ou pire, des variables globales. Rails.configuration.x permet de stocker l’ensemble des données de configuration pour une instance donnée et de récupérer très facilement ces infos depuis n’importe où dans l’application.

L’implémentation de Rails.configuration.x mérite qu’on s’y attarde ! Il s’agit d’une instance de la classe Custom déclarée comme ceci :

# railties/lib/rails/application/configuration.rb  module Rails   class Application     class Configuration < ::Rails::Engine::Configuration        def initialize(*)         @x = Custom.new       end        class Custom #:nodoc:         def initialize           @configurations = Hash.new         end          def method_missing(method, *args)           if method.end_with?("=")             @configurations[:"#{method[0..-2]}"] = args.first           else             @configurations.fetch(method) {               @configurations[method] = ActiveSupport::OrderedOptions.new             }           end         end          def respond_to_missing?(symbol, *)           true         end       end     end   end end 

On observe que la technique consiste à faire usage de la méthode method_missing, nous offrant ainsi la possibilité de récupérer ou d’affecter une valeur via n’importe quelle méthode de notre choix sur cet objet. On remarque que si la clé foo n’existe pas dans le dictionnaire @configurations, c’est-à-dire la première fois qu’on fait appel à Rails.configuration.foo, une nouvelle instance d’ActiveSupport::OrderedOptions.new est créée. Il s’agit d’une classe qui hérite de la classe Hash et qui fournit des accesseurs dynamiques.

Avec un Hash, les paires clé-valeur sont généralement manipulées comme ceci :

h = {} h[:boy] = 'John' h[:girl] = 'Mary' h[:boy]  # => 'John' h[:girl] # => 'Mary' h[:dog]  # => nil 

En utilisant un OrderedOptions, l’exemple ci-dessus peut être écrit comme ceci :

h = ActiveSupport::OrderedOptions.new h.boy = 'John' h.girl = 'Mary' h.boy  # => 'John' h.girl # => 'Mary' h.dog  # => nil 

Il est aussi possible de lever une exception si la valeur est manquante :

h.dog! # => raises KeyError: :dog is blank 

Dans ce contexte, l’utilisation conjointe de method_missing et OrderedOptions nous offre une grande souplesse à l’usage. C’est une approche intéressante, notamment dans le cas d’un framework ou d’une bibliothèque généraliste, mais coûteuse et déconseillée pour implémenter un code métier aux règles de gestion bien connues et maîtrisées.

Remarquons ici une bonne pratique souvent oubliée lorsqu’on fait usage de method_missing : implémenter également respond_to_missing? de manière à indiquer si la méthode que l’on s’apprête à utiliser est implémentée ou non à la volée par method_missing. Dans notre cas, on répondra toujours oui (true) parce que notre implémentation de method_missing se comportera toujours comme un accesseur, peu importe le nom de la méthode qu’on lui passe en argument.

À l’usage

Dans les faits, en suivant les recommandations précédentes, nous pourrions nous retrouver avec une configuration applicative qui ressemble à ceci :

# config/application.rb  module MyApp   class Application < Rails::Application   # …   config.x.api_url = ENV.fetch("API_URL")   config.x.api_scheme = ENV.fetch("API_SCHEME", "http")   config.x.enable_foo = ENV.fetch("ENABLE_FOO", 0).to_i.positive?   # …   end end 

Et l’utiliser de cette manière dans notre application :

Rails.configuration.x.api_url Rails.configuration.x.enable_foo == true 

Allons un peu plus loin

Rails nous offre un outil supplémentaire qui peut s’avérer fort utile, j’ai nommé config_for. Il s’agit d’un moyen de charger une configuration applicative à partir d’un fichier YAML. Cerise sur le gâteau, l’environnement courant de Rails est pris en compte ! Voici un petit exemple :

# config/api_custom.yml  defaults: &defaults   timeout: <%= ENV.fetch("API_CUSTOM_TIMEOUT", 20).to_i %>  development:   <<: *defaults   url: <%= ENV.fetch("API_CUSTOM_URL", "https://custom-dev.api.example.org/api/v2") %>  test:   <<: *defaults   url: https://custom-test.api.custom.org/api/v2  production:   <<: *defaults   url: <%= ENV.fetch("API_CUSTOM_URL", "https://custom.api.custom.org/api/v2") %> 
# config/application.rb  class Application < Rails::Application   # Custom Configuration   config.x.api_custom = config_for(:api_custom) end 

À présent, nous pouvons faire appel à notre configuration :

Rails.configuration.api_custom.timeout Rails.configuration.api_custom.url 

Avouez que c’est bien pratique ! Ainsi notre configuration applicative est à la fois centralisée et contextualisée ; fini les variables de configuration obscures qui surgissent d’on ne sait où !

Ressources

  • Rails custom configuration
  • Fail Fast, by Jim Shore

À lire aussi

Fresque numérique miniature image
16 avril 2025

Fresque du Numérique

Lire la suite

intelligence artificielle Ouicommit miniature image
17 mars 2025

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

Lire la suite

Image miniature Hackathon Women in Tech
13 mars 2025

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

Lire la suite

image miniature les nouveautés Atlassian
26 février 2025

Les nouveautés Atlassian en 2025

Lire la suite

Articles associés

Fresque numérique miniature image
16 avril 2025

Fresque du Numérique


Lire la suite
intelligence artificielle Ouicommit miniature image
17 mars 2025

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


Lire la suite
Image miniature Hackathon Women in Tech
13 mars 2025

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


Lire la suite

À propos

  • Qui sommes-nous ?
  • Références
  • RSE
  • Ressources

Offres

  • Applications métier
  • Collaboration des équipes
  • Sécurisation et optimisation du système d’information
  • Transformation numérique

Expertises

  • Développement logiciel
  • DevSecOps
  • Intégration de logiciels et négoce de licences
  • Logiciel de CRM et de gestion
  • UX/UI design
  • Accessibilité Numérique
  • Démarches simplifiées
  • Formations Atlassian

Carrières

  • Pourquoi rejoindre Ouidou ?
  • Nous rejoindre
  • Rencontrer nos collaborateurs
  • Grandir chez Ouidou

SIEGE SOCIAL
70-74 boulevard Garibaldi, 75015 Paris

Ouidou Nord
165 Avenue de Bretagne, 59000 Lille

Ouidou Rhône-Alpes
4 place Amédée Bonnet, 69002 Lyon

Ouidou Grand-Ouest
2 rue Crucy, 44000 Nantes

Ouidou Grand-Est
7 cour des Cigarières, 67000 Strasbourg

  • Linkedin Ouidou
  • GitHub Ouidou
  • Youtube Ouidou
© 2024 Ouidou | Tous droits réservés | Plan du site | Mentions légales | Déclaration d'accessibilité
    Nous contacter