window.pipedriveLeadboosterConfig = { base : 'leadbooster-chat.pipedrive.com', companyId : 11580370, playbookUuid: '22236db1-6d50-40c4-b48f-8b11262155be', version : 2, } ;(function () { var w = window if (w.LeadBooster) { console.warn('LeadBooster existe déjà') } else { w.LeadBooster = { q : [], on : function (n, h) { this.q.push({ t : 'o', n : n, h : h }) }, trigger : function (n) { this.q.push({ t : 't', n : n }) }, } } })() Polymorphisme en Ruby et GraphQL - The Codest
The Codest
  • A propos de nous
  • Services
    • Développement de logiciels
      • Développement frontal
      • Développement backend
    • Staff Augmentation
      • Développeurs frontaux
      • Développeurs backend
      • Ingénieurs des données
      • Ingénieurs en informatique dématérialisée
      • Ingénieurs AQ
      • Autres
    • Conseil consultatif
      • Audit et conseil
  • Industries
    • Fintech et banque
    • E-commerce
    • Adtech
    • Santé (Healthtech)
    • Fabrication
    • Logistique
    • Automobile
    • IOT
  • Valeur pour
    • CEO
    • CTO
    • Gestionnaire des livraisons
  • Notre équipe
  • Études de cas
  • Savoir comment
    • Blog
    • Rencontres
    • Webinaires
    • Ressources
Carrières Prendre contact
  • A propos de nous
  • Services
    • Développement de logiciels
      • Développement frontal
      • Développement backend
    • Staff Augmentation
      • Développeurs frontaux
      • Développeurs backend
      • Ingénieurs des données
      • Ingénieurs en informatique dématérialisée
      • Ingénieurs AQ
      • Autres
    • Conseil consultatif
      • Audit et conseil
  • Valeur pour
    • CEO
    • CTO
    • Gestionnaire des livraisons
  • Notre équipe
  • Études de cas
  • Savoir comment
    • Blog
    • Rencontres
    • Webinaires
    • Ressources
Carrières Prendre contact
Flèche arrière RETOUR
2022-01-13
Développement de logiciels

Polymorphisme en Ruby et GraphQL

Lukasz Brzeszcz

Dans cet article, je vais présenter l'utilisation du polymorphisme dans GraphQL. Mais avant de commencer, il convient de rappeler ce que sont le polymorphisme et GraphQL.

Polymorphisme

Polymorphisme est un élément clé de la la programmation orientée objet. Pour simplifier, elle est basée sur le fait que des objets de classes différentes ont accès à la même interface, ce qui signifie que l'on peut attendre de chacun d'eux la même fonctionnalité, mais pas nécessairement implémentée de la même manière. En Développeurs Ruby peut obtenir polymorphisme de trois manières :

Héritage

Héritage consiste à créer une classe mère et des classes enfants (c'est-à-dire héritant de la classe mère). Les sous-classes reçoivent les fonctionnalités de la classe mère et permettent également de modifier et d'ajouter une fonctionnalité.

Exemple :

classe Document
  attr_reader :name
fin

classe PDFDocument < Document
  def extension
    :pdf
  end
fin

classe ODTDocument < Document
  def extension
    :odt
  end
fin

Modules

Modules en Rubis ont de nombreuses utilisations. L'une d'entre elles est le mixage (pour en savoir plus sur les mixages, consultez la rubrique L'analyse ultime : Rubis vs. Python). Les mixins en Ruby peuvent être utilisés de la même manière que les interfaces dans d'autres langages de programmation (par exemple, en Java), par exemple, vous pouvez y définir des méthodes communes aux objets qui contiendront un mixin donné. Il est conseillé d'inclure des méthodes en lecture seule dans les modules, c'est-à-dire des méthodes qui ne modifieront pas l'état de cet objet.

Exemple :

module Taxable
  def tax

     prix * 0,23
  fin
fin

classe Voiture
  include Taxable
 attr_reader :prix
end

classe Livre
  include Taxable

 attr_reader :prix
end

Dactylographie du canard

C'est l'une des principales caractéristiques des langages à typage dynamique. Le nom vient du célèbre test "si ça ressemble à un canard, si ça nage comme un canard et si ça jacasse comme un canard, alors c'est probablement un canard". Le programmeur ne doit pas s'intéresser à la classe à laquelle appartient l'objet donné. Ce qui est important, ce sont les méthodes qui peuvent être appelées sur cet objet.

En utilisant les classes définies dans l'exemple ci-dessus :

classe Voiture
  attr_reader :prix

 def initialize(prix)
    @price = prix
   end
end

classe Book
  attr_reader :prix

 def initialize(prix)
    @price = prix
  end
end

car = Car.new(20.0)
book = Book.new(10.0)

[car, book].map(&:price

GrapQL

GraphQL est un langage de requête relativement nouveau pour les API. Il présente l'avantage d'avoir une syntaxe très simple et, en outre, le client décide de ce qu'il veut obtenir exactement, car chaque client reçoit exactement ce qu'il veut et rien d'autre.

Exemple de requête en GraphQL:

{
  allUsers {
     users {
        id
        login
        email

       }
     }
   }

Exemple de réponse :

{
  "allUsers" : {
    "users" : [
     {
        "id" : 1,
        "login" : "user1",
        "email" : "[email protected]"
      },
      {
        "id" : 2,
        "login" : "user2",
        "email" : "[email protected]"
      },
    ]
  }
}

C'est probablement tout ce que nous avons besoin de savoir pour l'instant. Alors, venons-en au fait.

Présentation du problème

Pour mieux comprendre le problème et sa solution, créons un exemple. Il serait bon que cet exemple soit à la fois original et assez terre à terre. Un exemple que chacun d'entre nous peut rencontrer un jour. Pourquoi pas... des animaux ? Oui ! Excellente idée !

polymorphisme ruby et grapql - animaux

Supposons que nous ayons une application dorsale écrite en Ruby on Rails. Il est déjà adapté pour gérer le schéma ci-dessus. Supposons également que nous ayons déjà GraphQL configuré. Nous voulons permettre au client de faire une demande dans la structure suivante :

{
 allZoos : {
    zoo : {
      nom
      ville
      animaux : {
        ...
      }
    }
  }
}

Nous verrons plus tard ce qu'il faut mettre à la place des trois points pour obtenir l'information manquante.

Mise en œuvre

Je présenterai ci-dessous les étapes nécessaires pour atteindre l'objectif.

Ajout d'une requête à QueryType

Tout d'abord, vous devez définir ce que signifie exactement la requête allZoos. Pour ce faire, nous devons visiter le fichierapp/graphql/types/query_type.rb et définir la requête :

   module Types
      class QueryType < Types::BaseObject
       field :all_zoos, [Types::ZooType], null : false

       def all_zoos
          Zoo.all
       end
    end
 end

La requête est déjà définie. Il est maintenant temps de définir les types de retour.

Définition des types

Le premier type requis sera ZooType. Définissons-le dans le fichier app/graphql/types/ zoo_type.rb:

module Types
  class ZooType < Types::BaseObject
    champ :name, Chaîne, null : false
    champ :city, Chaîne, null : false
    champ :animals, [Types::AnimalType], null : false
  end
end

Il est maintenant temps de définir le type AnimalType :

module Types
  class AnimalType < Types::BaseUnion
   possible_types ElephantType, CatType, DogType

     def self.resolve_type(obj, ctx)
       if obj.is_a ?(Elephant)
          ElephantType
       elsif obj.is_a ?(Cat)
         Type de chat
       elsif obj.is_a ?(Dog)
        Type Chien
      fin
    fin
  end
fin

Que voyons-nous dans la code ci-dessus ?

  1. Le type AnimalType hérite de Types::BaseUnion.
  2. Nous devons énumérer tous les types qui peuvent composer un syndicat donné.
    3. nous remplaçons la fonction self.resolve_object(obj, ctx),qui doit renvoyer le type d'un objet donné.

L'étape suivante consiste à définir les types d'animaux. Cependant, nous savons que certains champs sont communs à tous les animaux. Incluons-les dans le type AnimalInterface :

module Types
  module AnimalInterface
    include Types::BaseInterface

    champ :name, String, null : false
    field :age, Integer, null : false
  end
end

Avec cette interface, nous pouvons définir les types d'animaux spécifiques :

module Types
  class ElephantType < Types::BaseObject
    implémente Types::AnimalInterface

    champ :trunk_length, Float, null : false
  end
fin

module Types
  class CatType < Types::BaseObject
   implémente Types::AnimalInterface

   champ :hair_type, String, null : false
  end
fin

module Types
  class DogType < Types::BaseObject
    implémente Types::AnimalInterface

     champ :breed, String, null : false
  end
end

Ça y est ! Vous êtes prêts ! Une dernière question : comment pouvons-nous utiliser ce que nous avons fait du côté du client ?

Construire la requête

{
 allZoos : {
   zoo : {
      nom
      ville
      animals : {
        __typename

        ... on ElephantType {
          nom
          âge
          longueur du tronc
        }

         ... on CatType {
          nom
          âge
          hairType
         }
         ... on DogType {
          nom
          âge
          race
         }
       }
     }
   }
 }

Nous pouvons utiliser un champ __typename supplémentaire ici, qui renverra le type exact d'un élément donné (par exemple, CatType). À quoi ressemblera un exemple de réponse ?

{
  "allZoos" : [

   {
      "name" : "Natura Artis Magistra",
      "city" : "Amsterdam",
      "animaux" : [
        {
          "__typename" : "ElephantType"
          "name" : "Franco",
          "âge" : 28,
          "trunkLength" : 9.27
         },
         {
         "__typename" : "DogType"
         "nom" : "Jack",
         "âge" : 9,
         "race" : "Terrier Jack Russell"
        },
      ]
    }
  ]
} 

Analyse

L'inconvénient de cette approche est évident. Dans la requête, nous devons saisir le nom et l'âge pour chaque type, même si nous savons que tous les animaux possèdent ces champs. Cela n'est pas gênant lorsque la collection contient des objets complètement différents. Dans ce cas, cependant, les animaux partagent presque tous les champs. Peut-on l'améliorer d'une manière ou d'une autre ?

Bien sûr ! Nous effectuons la première modification dans le fichier app/graphql/types/zoo_type.rb:

module Types
  class ZooType < Types::BaseObject
    champ :name, String, null : false
    champ :city, Chaîne, null : false
    champ :animals, [Types::AnimalInterface], null : false
  end
end

Nous n'avons plus besoin de l'union que nous avions définie auparavant. Nous changeons Types::AnimalType à Types::AnimalInterface.

L'étape suivante consiste à ajouter une fonction qui renvoie un type de Types : : AnimalInterface et ajoute également une liste de types orphelins, c'est-à-dire de types qui ne sont jamais utilisés directement :

module Types
  module AnimalInterface
    include Types::BaseInterface

   champ :name, String, null : false
   champ :age, Integer, null : false

   definition_methods do
      def resolve_type(obj, ctx)
        if obj.is_a ?(Elephant)
          ElephantType
        elsif obj.is_a ?(Cat)
          CatType
        elsif obj.is_a ?(Dog)
          Type Chien
        end
      fin
    fin
    orphan_types Types::ElephantType, Types::CatType, Types::DogType
  fin
fin

Grâce à cette procédure simple, la requête a une forme moins complexe :

{
  allZoos : {
   zoo : {
      nom
      ville
      animals : {
        __typename
        nom
        âge

       ... on ElephantType {
          longueur du tronc

       }
       ... on CatType {
          hairType

       }
       ... on DogType {
          race

        }
      }
    }
  }
}

Résumé

GraphQL est une très bonne solution. Si vous ne la connaissez pas encore, essayez-la. Croyez-moi, cela en vaut la peine. Elle permet de résoudre les problèmes apparaissant, par exemple, dans les API REST. Comme je l'ai montré plus haut, polymorphisme n'est pas un véritable obstacle. J'ai présenté deux méthodes pour l'aborder.
Rappel :

  • Si vous opérez sur une liste d'objets ayant une base commune ou une interface commune, utilisez les interfaces,
  • Si vous opérez sur une liste d'objets ayant une structure différente, utilisez une interface différente - utilisez l'union

Lire la suite

GraphQL Ruby. Qu'en est-il des performances ?

Rails et autres moyens de transport

Développement Rails avec TMUX, Vim, Fzf + Ripgrep

Articles connexes

Développement de logiciels

Construire des applications web à l'épreuve du temps : les conseils de l'équipe d'experts de The Codest

Découvrez comment The Codest excelle dans la création d'applications web évolutives et interactives à l'aide de technologies de pointe, offrant une expérience utilisateur transparente sur toutes les plateformes. Découvrez comment notre expertise favorise la transformation numérique et la...

LE CODEST
Développement de logiciels

Les 10 premières entreprises de développement de logiciels basées en Lettonie

Découvrez les principales sociétés de développement de logiciels en Lettonie et leurs solutions innovantes dans notre dernier article. Découvrez comment ces leaders de la technologie peuvent vous aider à développer votre entreprise.

thecodest
Solutions pour les entreprises et les grandes entreprises

L'essentiel du développement de logiciels Java : Un guide pour une externalisation réussie

Explorez ce guide essentiel sur le développement réussi de logiciels Java outsourcing pour améliorer l'efficacité, accéder à l'expertise et assurer la réussite des projets avec The Codest.

thecodest
Développement de logiciels

Le guide ultime de l'externalisation en Pologne

L'essor de outsourcing en Pologne est dû aux progrès économiques, éducatifs et technologiques, qui favorisent la croissance des technologies de l'information et un climat propice aux entreprises.

TheCodest
Solutions pour les entreprises et les grandes entreprises

Le guide complet des outils et techniques d'audit informatique

Les audits informatiques garantissent la sécurité, l'efficacité et la conformité des systèmes. Pour en savoir plus sur leur importance, lisez l'article complet.

The Codest
Jakub Jakubowicz CTO & Co-Fondateur

Abonnez-vous à notre base de connaissances et restez au courant de l'expertise du secteur des technologies de l'information.

    A propos de nous

    The Codest - Entreprise internationale de développement de logiciels avec des centres technologiques en Pologne.

    Royaume-Uni - Siège

    • Bureau 303B, 182-184 High Street North E6 2JA
      Londres, Angleterre

    Pologne - Les pôles technologiques locaux

    • Parc de bureaux Fabryczna, Aleja
      Pokoju 18, 31-564 Kraków
    • Brain Embassy, Konstruktorska
      11, 02-673 Varsovie, Pologne

      The Codest

    • Accueil
    • A propos de nous
    • Services
    • Études de cas
    • Savoir comment
    • Carrières
    • Dictionnaire

      Services

    • Conseil consultatif
    • Développement de logiciels
    • Développement backend
    • Développement frontal
    • Staff Augmentation
    • Développeurs backend
    • Ingénieurs en informatique dématérialisée
    • Ingénieurs des données
    • Autres
    • Ingénieurs AQ

      Ressources

    • Faits et mythes concernant la coopération avec un partenaire externe de développement de logiciels
    • Des États-Unis à l'Europe : Pourquoi les startups américaines décident-elles de se délocaliser en Europe ?
    • Comparaison des pôles de développement Tech Offshore : Tech Offshore Europe (Pologne), ASEAN (Philippines), Eurasie (Turquie)
    • Quels sont les principaux défis des CTO et des DSI ?
    • The Codest
    • The Codest
    • The Codest
    • Privacy policy
    • Conditions d'utilisation du site web

    Copyright © 2025 par The Codest. Tous droits réservés.

    fr_FRFrench
    en_USEnglish de_DEGerman sv_SESwedish da_DKDanish nb_NONorwegian fiFinnish pl_PLPolish arArabic it_ITItalian jaJapanese ko_KRKorean es_ESSpanish nl_NLDutch etEstonian elGreek fr_FRFrench