window.pipedriveLeadboosterConfig = { basis: 'leadbooster-chat.pipedrive.com', companyId: 11580370, playbookUuid: '22236db1-6d50-40c4-b48f-8b11262155be', versie: 2, } ;(functie () { var w = venster als (w.LeadBooster) { console.warn('LeadBooster bestaat al') } anders { w.LeadBooster = { q: [], on: functie (n, h) { this.q.push({ t: 'o', n: n, h: h }) }, trigger: functie (n) { this.q.push({ t: 't', n: n }) }, } } })() Polymorfisme in Ruby en GraphQL - The Codest
The Codest
  • Over ons
  • Diensten
    • Software Ontwikkeling
      • Frontend ontwikkeling
      • Backend ontwikkeling
    • Staff Augmentation
      • Frontend ontwikkelaars
      • Backend ontwikkelaars
      • Gegevensingenieurs
      • Cloud Ingenieurs
      • QA ingenieurs
      • Andere
    • Het advies
      • Audit & Consulting
  • Industrie
    • Fintech & Bankieren
    • E-commerce
    • Adtech
    • Gezondheidstechnologie
    • Productie
    • Logistiek
    • Automotive
    • IOT
  • Waarde voor
    • CEO
    • CTO
    • Leveringsmanager
  • Ons team
  • Case Studies
  • Weten hoe
    • Blog
    • Ontmoetingen
    • Webinars
    • Bronnen
Carrière Neem contact op
  • Over ons
  • Diensten
    • Software Ontwikkeling
      • Frontend ontwikkeling
      • Backend ontwikkeling
    • Staff Augmentation
      • Frontend ontwikkelaars
      • Backend ontwikkelaars
      • Gegevensingenieurs
      • Cloud Ingenieurs
      • QA ingenieurs
      • Andere
    • Het advies
      • Audit & Consulting
  • Waarde voor
    • CEO
    • CTO
    • Leveringsmanager
  • Ons team
  • Case Studies
  • Weten hoe
    • Blog
    • Ontmoetingen
    • Webinars
    • Bronnen
Carrière Neem contact op
Pijl terug KEREN TERUG
2022-01-13
Software Ontwikkeling

Polymorfisme in Ruby en GraphQL

Lukasz Brzeszcz

In dit artikel presenteer ik het gebruik van polymorfisme in GraphQL. Voordat ik begin, is het echter de moeite waard om in herinnering te brengen wat polymorfisme en GraphQL zijn.

Polymorfisme

Polymorfisme is een belangrijk onderdeel van objectgeoriënteerd programmeren. Om de zaken te vereenvoudigen, is het gebaseerd op het feit dat objecten van verschillende klassen toegang hebben tot dezelfde interface, wat betekent dat we van elk van hen dezelfde functionaliteit kunnen verwachten, maar niet noodzakelijk op dezelfde manier geïmplementeerd. In Ruby ontwikkelaars kunnen verkrijgen polymorfisme op drie manieren:

Erfenis

Erfenis bestaat uit het maken van een ouderklasse en kindklassen (d.w.z. die overerven van de ouderklasse). Subklassen krijgen de functionaliteit van de ouderklasse en stellen je ook in staat om functionaliteit te wijzigen of toe te voegen.

Voorbeeld:

klasse Document
  attr_lezer :naam
einde

klasse PDFDocument < Document
  def uitbreiding
    :pdf
  einde
einde

klasse ODTDocument < Document
  Uitbreiding
    :odt
  einde
einde

Modules

Modules in Ruby hebben veel toepassingen. Een daarvan is mixins (lees meer over mixins in De ultieme onderverdeling: Ruby vs. Python). Mixins in Ruby kunnen op dezelfde manier gebruikt worden als interfaces in andere programmeertalen (bijvoorbeeld in Java), bijvoorbeeld, kun je daarin methoden definiëren die gemeenschappelijk zijn voor objecten die een bepaalde mixin zullen bevatten. Het is een goede gewoonte om alleen-lezen methoden in modules op te nemen, dus methoden die de toestand van dit object niet wijzigen.

Voorbeeld:

module Belastbaar
  def. belasting

     prijs * 0,23
  einde
einde

Klasse Auto
  inclusief belastbaar
 attr_lezer :prijs
einde

Klasse Boek
  include belastingplichtige

 attr_lezer :prijs
einde

Typen met eend

Dit is een van de belangrijkste eigenschappen van dynamisch getypeerde talen. De naam komt van de beroemde test als het eruit ziet als een eend, zwemt als een eend en kwaakt als een eend, dan is het waarschijnlijk een eend. De programmeur hoeft niet geïnteresseerd te zijn tot welke klasse het gegeven object behoort. Wat belangrijk is, zijn de methoden die op dit object kunnen worden aangeroepen.

Gebruik de klassen die in het bovenstaande voorbeeld zijn gedefinieerd:

Klasse Auto
  attr_lezer :prijs

 def initialiseer(prijs)
    @prijs = prijs
   einde
einde

Klasse Boek
  attr_lezer :prijs

 def initialiseer(prijs)
    @prijs = prijs
  einde
einde

auto = auto.nieuw(20.0)
boek = boek.nieuw(10.0)

[auto, boek].map(&:prijs

GrapQL

GraphQL is een relatief nieuwe querytaal voor API's. De voordelen zijn onder andere dat het een zeer eenvoudige syntaxis heeft en bovendien bepaalt de klant wat hij precies wil krijgen, omdat elke klant precies krijgt wat hij wil en niets anders.

Voorbeeldvraag in GraphQL:

{
  allUsers {
     users {
        id
        login
        e-mail

       }
     }
   }

Voorbeeldantwoord:

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

Dit is waarschijnlijk alles wat we op dit moment moeten weten. Laten we ter zake komen.

Presentatie van het probleem

Om het probleem en de oplossing zo goed mogelijk te begrijpen, laten we een voorbeeld maken. Het zou goed zijn als het voorbeeld zowel origineel als redelijk nuchter was. Een voorbeeld dat ieder van ons op een dag kan tegenkomen. Wat dacht je van... dieren? Ja! Goed idee!

ruby en grapql polymorfisme - dieren

Stel dat we een back-end applicatie hebben die geschreven is in Ruby on Rails. Het is al aangepast aan het bovenstaande schema. Laten we ook aannemen dat we al GraphQL geconfigureerd. We willen de klant in staat stellen een aanvraag te doen binnen de volgende structuur:

{
 allZoos : {
    zoo: {
      naam
      stad
      dieren: {
        ...
      }
    }
  }
}

Wat er in plaats van de drie puntjes moet worden gezet om de ontbrekende informatie te krijgen - daar komen we later wel achter.

Implementatie

Hieronder presenteer ik de stappen die nodig zijn om het doel te bereiken.

Een query toevoegen aan QueryType

Eerst moet je definiëren wat de query allZoos precies betekent. Hiervoor moeten we naar het bestandapp/graphql/types/query_type.rb en definieer de query:

   module Types
      klasse QueryType < Types::BaseObject
       veld :all_zoos, [Types::ZooType], null: false

       def alle_zoös
          Dierentuin.alle
       einde
    einde
 einde

De query is al gedefinieerd. Nu is het tijd om de retoursoorten te definiëren.

Definitie van soorten

Het eerste type dat nodig is, is ZooType. Laten we het definiëren in het bestand app/graphql/types/ zoo_type.rb:

module Types
  klasse Dierentype < Types::BaseObject
    veld :name, String, null: false
    veld :city, String, nul: vals
    veld :animals, [Types::AnimalType], nul: vals
  einde
einde

Nu is het tijd om het type AnimalType te definiëren:

module Typen
  Klasse DierType < Types::BaseUnion
   mogelijke_typen OlifantType, KatType, HondType

     def self.resolve_type(obj, ctx)
       als obj.is_een?(Olifant)
          OlifantType
       als obj.is_een?(Kat)
         CatType
       anders indien obj.is_een?(Hond)
        HondType
      eind
    einde
  einde
einde

Wat zien we in de code boven?

  1. Het AnimalType erft van Types::BaseUnion.
  2. We moeten een lijst maken van alle typen die een bepaalde unie kunnen vormen.
    3.We overschrijven de functie self.resolve_object(obj, ctx),die het type van een gegeven object moet teruggeven.

De volgende stap is het definiëren van de soorten dieren. We weten echter dat sommige velden gemeenschappelijk zijn voor alle dieren. Laten we ze opnemen in het type AnimalInterface:

module Typen
  module Dierlijke interface
    include Types::BaseInterface

    veld :name, String, null: false
    veld :leeftijd, geheel getal, nul: vals
  einde
einde

Met deze interface kunnen we de soorten specifieke dieren definiëren:

module Types
  Klasse OlifantType < Types::BaseObject
    implementeert Types::AnimalInterface

    veld :slurf_lengte, Vlotter, nul: vals
  einde
einde

module Types
  Klasse Kattype < Types::BaseObject
   implementeert Types::AnimalInterface

   veld :hair_type, String, null: false
  einde
einde

module Types
  Klasse HondType < Types::BaseObject
    implementeert Types::AnimalInterface

     veld :ras, String, nul: vals
  einde
einde

Dat is het! Klaar! Nog een laatste vraag: hoe kunnen we gebruiken wat we aan de kant van de klant hebben gedaan?

De query bouwen

{
 allZoos : {
   zoo: {
      naam
      stad
      dieren: {
        __typenaam

        ... op ElephantType {
          naam
          leeftijd
          trunkLength
        }

         ... op CatType {
          naam
          age
          hairType
         }
         ... on DogType {
          naam
          age
          ras
         }
       }
     }
   }
 }

We kunnen hier een extra __typename veld gebruiken, dat het exacte type van een gegeven element teruggeeft (bijvoorbeeld CatType). Hoe ziet een voorbeeldantwoord eruit?

{
  "allZoos": [

   {
      "naam": "Natura Artis Magistra",
      "stad": "Amsterdam",
      "dieren": [
        {
          "__typenaam": "ElephantType".
          "naam "Franco",
          "age": 28,
          "trunkLength": 9.27
         },
         {
         "__typename": "DogType
         "naam": "Jack",
         "age": 9,
         "ras": "Jack Russell Terrier"
        },
      ]
    }
  ]
} 

Analyse

Eén nadeel van deze aanpak is duidelijk. In de query moeten we bij elk type de naam en leeftijd invoeren, ook al weten we dat alle dieren deze velden hebben. Dit is niet hinderlijk als de verzameling compleet verschillende objecten bevat. In dit geval delen de dieren echter bijna alle velden. Kan dit op de een of andere manier worden verbeterd?

Natuurlijk! We maken de eerste wijziging in het bestand app/graphql/types/zoo_type.rb:

module Types
  klasse Dierentype < Types::BaseObject
    veld :name, String, null: false
    veld :city, String, null: false
    veld :animals, [Types::AnimalInterface], nul: vals
  einde
einde

We hebben de unie die we eerder hebben gedefinieerd niet langer nodig. We veranderen Types::AnimalType naar Types::AnimalInterface.

De volgende stap is het toevoegen van een functie die een type teruggeeft van Typen :: AnimalInterface en voeg ook een lijst met orphan_types toe, dus types die nooit direct gebruikt worden:

module Typen
  module Dierlijke interface
    include Types::BaseInterface

   veld :name, String, null: false
   veld :leeftijd, geheel getal, nul: vals

   definitie_methoden doen
      def resolve_type(obj, ctx)
        als obj.is_een?(Olifant)
          OlifantType
        als obj.is_een?(Kat)
          CatType
        als obj.is_een?(Hond)
          HondType
        eind
      einde
    einde
    orphan_types Types::ElephantType, Types::CatType, Types::DogType
  eind
einde

Dankzij deze eenvoudige procedure heeft de query een minder complexe vorm:

{
  allZoos : {
   zoo: {
      naam
      stad
      dieren: {
        __typenaam
        naam
        leeftijd

       ... op ElephantType {
          slurflengte

       }
       ... op CatType {
          hairType

       }
       ... op DogType {
          ras

        }
      }
    }
  }
}

Samenvatting

GraphQL is echt een geweldige oplossing. Als je het nog niet kent, probeer het dan. Geloof me, het is de moeite waard. Het werkt geweldig bij het oplossen van problemen die zich voordoen in bijvoorbeeld REST API's. Zoals ik hierboven heb laten zien, polymorfisme is niet echt een obstakel. Ik heb twee methoden gepresenteerd om het aan te pakken.
Herinnering:

  • Als je werkt op een lijst van objecten met een gemeenschappelijke basis of een gemeenschappelijke interface - gebruik dan de interfaces,
  • Als je werkt op een lijst van objecten met een andere structuur, gebruik dan een andere interface - gebruik de unie

Meer lezen

GraphQL Ruby. Hoe zit het met de prestaties?

Rails en andere transportmiddelen

Rails ontwikkelen met TMUX, Vim, Fzf + Ripgrep

Verwante artikelen

Software Ontwikkeling

Bouw Toekomstbestendige Web Apps: Inzichten van The Codest's Expert Team

Ontdek hoe The Codest uitblinkt in het creëren van schaalbare, interactieve webapplicaties met geavanceerde technologieën, het leveren van naadloze gebruikerservaringen op alle platforms. Ontdek hoe onze expertise digitale transformatie en business...

DE BESTE
Software Ontwikkeling

Top 10 in Letland gevestigde bedrijven voor softwareontwikkeling

Lees meer over de beste softwareontwikkelingsbedrijven van Letland en hun innovatieve oplossingen in ons nieuwste artikel. Ontdek hoe deze technologieleiders uw bedrijf kunnen helpen verbeteren.

thecodest
Oplossingen voor ondernemingen en schaalvergroting

Essentiële Java-softwareontwikkeling: Een gids voor succesvol uitbesteden

Verken deze essentiële gids over succesvolle outsourcing Java-softwareontwikkeling om de efficiëntie te verbeteren, toegang te krijgen tot expertise en projectsucces te stimuleren met The Codest.

thecodest
Software Ontwikkeling

De ultieme gids voor outsourcing in Polen

De sterke groei van outsourcing in Polen wordt gedreven door economische, educatieve en technologische vooruitgang, die IT-groei en een bedrijfsvriendelijk klimaat stimuleert.

DeCodest
Oplossingen voor ondernemingen en schaalvergroting

De complete gids voor IT-auditmiddelen en -technieken

IT-audits zorgen voor veilige, efficiënte en compliant systemen. Lees het volledige artikel om meer te weten te komen over het belang ervan.

The Codest
Jakub Jakubowicz CTO & medeoprichter

Abonneer je op onze kennisbank en blijf op de hoogte van de expertise uit de IT-sector.

    Over ons

    The Codest - Internationaal softwareontwikkelingsbedrijf met technische hubs in Polen.

    Verenigd Koninkrijk - Hoofdkantoor

    • Kantoor 303B, 182-184 High Street North E6 2JA
      Londen, Engeland

    Polen - Lokale technologieknooppunten

    • Fabryczna kantorenpark, Aleja
      Pokoju 18, 31-564 Krakau
    • Hersenambassade, Konstruktorska
      11, 02-673 Warschau, Polen

      The Codest

    • Home
    • Over ons
    • Diensten
    • Case Studies
    • Weten hoe
    • Carrière
    • Woordenboek

      Diensten

    • Het advies
    • Software Ontwikkeling
    • Backend ontwikkeling
    • Frontend ontwikkeling
    • Staff Augmentation
    • Backend ontwikkelaars
    • Cloud Ingenieurs
    • Gegevensingenieurs
    • Andere
    • QA ingenieurs

      Bronnen

    • Feiten en fabels over samenwerken met een externe partner voor softwareontwikkeling
    • Van de VS naar Europa: Waarom Amerikaanse startups besluiten naar Europa te verhuizen
    • Tech Offshore Ontwikkelingshubs Vergelijking: Tech Offshore Europa (Polen), ASEAN (Filippijnen), Eurazië (Turkije)
    • Wat zijn de grootste uitdagingen voor CTO's en CIO's?
    • The Codest
    • The Codest
    • The Codest
    • Privacy policy
    • Gebruiksvoorwaarden website

    Copyright © 2025 door The Codest. Alle rechten voorbehouden.

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