• 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
✕
Yes, OuiJump, le jeu conçu et développé par Ouidou
Yes, OuiJump, le jeu conçu et développé par Ouidou
1 décembre 2021
Modes de déploiement continu : Rolling-upgrade, Blue-Green, Canary
Modes de déploiement continu : Rolling-upgrade, Blue-Green, Canary
21 décembre 2021
Ressources > Articles techniques > Manipuler ses données avec dry-transformer

Manipuler ses données avec dry-transformer

Article écrit par Emilie Podczaszy

La manipulation de données est une tâche que nous faisons quotidiennement, renommer les paramètres d’une requête entrante dans un contrôleur, exporter des tableaux de données diverses en CSV, etc. La liste est longue et selon la complexité des structures à manipuler ou du résultat attendu, la tâche peut vite devenir ardue.

Après avoir entendu parler de la gem dry-transformer, j’ai décidé de la tester et contre toute attente, elle répond parfaitement à la problématique tout en étant simple d’utilisation. Seul point négatif, son manque de documentation et d’exemples, c’est pourquoi je vous propose de voir ensemble comment elle fonctionne et s’utilise.

Dry-transformer, qu’est-ce que c’est ?

Cette petite bibliothèque Ruby, qui fait partie de la collection des gems dry-rb, est inspirée de la programmation fonctionnelle : les données passent à travers plusieurs fonctions “stateless” qui chacune renvoie une nouvelle représentation des données d’origine à la fonction suivante. Elle propose donc une approche plus orientée donnée qu’orientée objet.

Il est aussi bon d’ajouter que la gem n’a aucune dépendance.

Exemple d’utilisation

Suite à un appel API, nous recevons cette liste de villes :

input = [   {     "nom" => "Lille",     "surface" => 34.8,     "population" => 232741,     "coordonnées" => {       "latitude" => 50.62925,       "longitude" => 3.057256     },   },   {     "nom" => "Amiens",     "surface" => 49.46,     "population" => 132874,     "coordonnées" => {       "latitude" => 49.894067,       "longitude" => 2.295753     }   },   {     "nom" => "Arras",     "surface" => 11.63,     "population" => 40721,     "coordonnées" => {       "latitude" => 50.291002,       "longitude" => 2.777535     }   },  ] 

Et souhaitons travailler un peu ce tableau pour obtenir :

[   {     name: "LILLE",     density: 6687.96,     latitude: 50.62925,     longitude: 3.057256   },   {     name: "ARRAS",     density: 3501.38,     latitude: 50.291002,     longitude: 2.777535   },   {     name: "AMIENS",     density: 2686.49,     latitude: 49.894067,     longitude: 2.295753   }, ] 

On veut donc appliquer les modifications suivantes :

  1. transformer toutes les clefs, mêmes celles imbriquées, en symboles ;
  2. renommer la clef nom par name ;
  3. mettre en majuscule le nom des villes ;
  4. extraire la latitude et la longitude des coordonnées ;
  5. calculer la densité de population ;
  6. ne garder que les paires clef-valeur qui nous intéresse ;
  7. trier le tableau par densité.

Tout d’abord, nous allons utiliser le DSL de la gem pour retranscrire chacune de ces étapes :

class Mapper < Dry::Transformer::Pipe   import Dry::Transformer::ArrayTransformations   import Dry::Transformer::HashTransformations    define! do     map_array do       deep_symbolize_keys                             # 1.       rename_keys nom: :name                          # 2.       map_value :name, -> value { value.upcase }      # 3.       unwrap :coordonnees, %i[latitude longitude]     # 4.       accept_keys %i[name density latitude longitude] # 6.     end   end end 

Importer les modules ArrayTransformations et HashTransformations mis à disposition par la gem permet d’appeler un certains nombres de fonctions de transformation. Pour notre exemple, presque tout est couvert, il ne reste que les étapes de calcul de la densité (5.) ainsi que le tri (7.).

Nous allons donc devoir créer notre propre module et pour cela rien de plus simple, il suffit d’étendre le module Registry et d’ajouter nos méthodes :

module CustomTransformations   extend Dry::Transformer::Registry    def self.add_key(hash, key, fn)     hash.merge(key => fn[hash])   end    def self.sort_by(array, key)     array.sort_by { |v| v[key] }   end end 

La méthode :sort_by est somme toute assez explicite, alors voyons plus en détails :add_key. Cette méthode prend en entrée notre hash, la clef à ajouter ainsi qu’un Proc qui sera invoqué avec :[] comme il est d’usage dans cette gem. Le tout sera fusionné avec le hash en entrée. Cela suit le même mode de fonctionnement que map_value utilisé plus haut.

Intégré dans notre mapper, cela donne :

define! do   map_array do     add_key :density, -> city { city[:population] / city[:surface] }   end end 

À noter qu’il y a d’autres manières d’utiliser un Proc :

compute_density = Proc.new { |city| city[:population] / city[:surface] } add_key :density, compute_density  # ou encore  class DensityComputation   def self.to_proc     proc { |city| city[:population] / city[:surface] }   end end add_key :density, DensityComputation.to_proc 

Un calcul, aussi simple soit-il, semble être un bon candidat pour une abstraction supplémentaire alors, gardons la classe DensityComputation.

Nous avons toutes nos transformations, il ne reste plus qu’à les ajouter dans le mapper et voilà :

class Mapper < Dry::Transformer::Pipe   import Dry::Transformer::ArrayTransformations   import Dry::Transformer::HashTransformations   import CustomTransformations    define! do     map_array do       deep_symbolize_keys                             # 1.       rename_keys nom: :name                          # 2.       map_value :name, -> value { value.upcase }      # 3.       unwrap :coordonnees, %i[latitude longitude]     # 4.       add_key :density, DensityComputation.to_proc    # 5.       accept_keys %i[name density latitude longitude] # 6.     end     sort_by :density                                  # 7.   end end  Mapper.new.call(input) => [   { name: "AMIENS", density: 2686.49, latitude: 49.894067, longitude: 2.295753 },   { name: "ARRAS",  density: 3501.38, latitude: 50.291002, longitude: 2.777535 },   { name: "LILLE",  density: 6687.96, latitude: 50.62925,  longitude: 3.057256 }, ] 

Chaque type de transformation est encapsulé dans sa méthode, ce qui rend la composition de plusieurs transformations facile et grâce au DSL le tout se lit simplement.

Un dernier pour la route

Si vous n’êtes toujours pas convaincu·e, voici un autre exemple.

On vous demande d’apporter des modifications dans un projet existant, vous préférez tomber sur cette méthode ?

def group_categories(array)   array.group_by{ |h| h[:name] }.values.map do |hs|     hs.first.merge({ categories: hs.map{ |h| h[:category] } }).except(:category)   end end 

Ou cette classe ?

class Mapper < Dry::Transformer::Pipe   import Dry::Transformer::ArrayTransformations   import Dry::Transformer::HashTransformations    define! do     group :categories, [:category]     map_array do       map_value :categories do         extract_key :category       end     end   end end 

Personnellement le choix est vite vu, dry-transformer rend le code bien plus compréhensible et maintenable.

Ressources

  • Complex Ruby Transformations made simple with dry-transformer ! par Seb Wilgosz

À 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