window.pipedriveLeadboosterConfig = { base: 'leadbooster-chat.pipedrive.com', companyId: 11580370, playbookUuid: '22236db1-6d50-40c4-b48f-8b11262155be', version: 2, } ;(function () { var w = Fenster if (w.LeadBooster) { console.warn('LeadBooster existiert bereits') } 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 }) }, } } })() Polymorphismus in Ruby und GraphQL - The Codest
Der Codest
  • Über uns
  • Dienstleistungen
    • Software-Entwicklung
      • Frontend-Softwareentwicklung
      • Backend-Softwareentwicklung
    • Staff Augmentation
      • Frontend-Entwickler
      • Backend-Entwickler
      • Daten-Ingenieure
      • Cloud-Ingenieure
      • QS-Ingenieure
      • Andere
    • IT-Beratung
      • Prüfung und Beratung
  • Branchen
    • Fintech & Bankwesen
    • E-commerce
    • Adtech
    • Gesundheitstechnik
    • Herstellung
    • Logistik
    • Automobilindustrie
    • IOT
  • Wert für
    • CEO
    • CTO
    • Delivery Manager
  • Unser Team
  • Fallstudien
  • Gewusst wie
    • Blog
    • Begegnungen
    • Webinare
    • Ressourcen
Karriere Kontakt aufnehmen
  • Über uns
  • Dienstleistungen
    • Software-Entwicklung
      • Frontend-Softwareentwicklung
      • Backend-Softwareentwicklung
    • Staff Augmentation
      • Frontend-Entwickler
      • Backend-Entwickler
      • Daten-Ingenieure
      • Cloud-Ingenieure
      • QS-Ingenieure
      • Andere
    • IT-Beratung
      • Prüfung und Beratung
  • Wert für
    • CEO
    • CTO
    • Delivery Manager
  • Unser Team
  • Fallstudien
  • Gewusst wie
    • Blog
    • Begegnungen
    • Webinare
    • Ressourcen
Karriere Kontakt aufnehmen
Pfeil zurück ZURÜCK
2022-01-13
Software-Entwicklung

Polymorphismus in Ruby und GraphQL

Lukasz Brzeszcz

In diesem Artikel werde ich die Verwendung von Polymorphismus in GraphQL vorstellen. Bevor ich jedoch damit beginne, sollte man sich in Erinnerung rufen, was Polymorphismus und GraphQL sind.

Polymorphismus

Polymorphismus ist eine Schlüsselkomponente von objektorientierte Programmierung. Der Einfachheit halber basiert sie auf der Tatsache, dass Objekte verschiedener Klassen Zugriff auf dieselbe Schnittstelle haben, was bedeutet, dass wir von jeder von ihnen dieselbe Funktionalität erwarten können, die aber nicht unbedingt auf dieselbe Weise implementiert ist. In Ruby-Entwickler erhalten können Polymorphismus auf drei Arten:

Vererbung

Vererbung besteht darin, eine übergeordnete Klasse und untergeordnete Klassen (d. h., die von der übergeordneten Klasse erben) zu erstellen. Unterklassen erhalten die Funktionalität der übergeordneten Klasse und ermöglichen es Ihnen auch, eine Funktionalität zu ändern und hinzuzufügen.

Beispiel:

Klasse Dokument
  attr_leser :name
end

class PDFDocument < Dokument
  def extension
    :pdf
  end
end

class ODTDocument < Dokument
  def Erweiterung
    :odt
  end
end

Module

Module in Rubinrot haben viele Verwendungsmöglichkeiten. Eine davon sind Mixins (lesen Sie mehr über Mixins in Die ultimative Aufschlüsselung: Ruby vs. Python). Mixins können in Ruby ähnlich wie Schnittstellen in anderen Programmiersprachen verwendet werden (z. B. in Java) können Sie zum Beispiel Methoden definieren, die allen Objekten gemeinsam sind, die ein bestimmtes Mixin enthalten werden. Es ist eine gute Praxis, schreibgeschützte Methoden in Module aufzunehmen, also Methoden, die den Zustand des Objekts nicht verändern.

Beispiel:

Modul steuerpflichtig
  Def-Steuer

     Preis * 0,23
  end
end

Klasse Auto
  include steuerpflichtig
 attr_leser :preis
end

class Buch
  include steuerpflichtig

 attr_leser :preis
end

Ente tippen

Dies ist eine der wichtigsten Eigenschaften dynamisch typisierter Sprachen. Der Name stammt von dem berühmten Test: Wenn es wie eine Ente aussieht, wie eine Ente schwimmt und wie eine Ente quakt, dann ist es wahrscheinlich eine Ente. Die Programmierer muss sich nicht dafür interessieren, zu welcher Klasse das gegebene Objekt gehört. Wichtig sind die Methoden, die auf diesem Objekt aufgerufen werden können.

Verwenden Sie die im obigen Beispiel definierten Klassen:

Klasse Auto
  attr_leser :preis

 def initialize(preis)
    @Preis = Preis
   end
end

class Buch
  attr_leser :preis

 def initialize(preis)
    @Preis = Preis
  end
end

Auto = Auto.neu(20.0)
Buch = Buch.neu(10.0)

[Auto, Buch].map(&:Preis

GrapQL

GraphQL ist eine relativ neue Abfragesprache für APIs. Zu ihren Vorteilen gehört die Tatsache, dass sie eine sehr einfache Syntax hat und außerdem der Kunde entscheidet, was genau er erhalten möchte, da jeder Kunde genau das bekommt, was er möchte und nichts anderes.

Beispielabfrage in GraphQL:

{
  allUsers {
     Benutzer {
        id
        Anmeldung
        E-Mail

       }
     }
   }

Beispielhafte Antwort:

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

Das ist wahrscheinlich alles, was wir im Moment wissen müssen. Also, kommen wir zur Sache.

Darstellung des Problems

Um das Problem und seine Lösung besser zu verstehen, sollten wir uns ein Beispiel ausdenken. Es wäre gut, wenn das Beispiel sowohl originell als auch ziemlich bodenständig wäre. Eines, das jedem von uns eines Tages begegnen kann. Wie wäre es mit... Tieren? Ja! Tolle Idee!

ruby und grapql polymorphismus - tiere

Angenommen, wir haben eine Backend-Anwendung, die in Ruby on Rails. Sie ist bereits an das obige Schema angepasst. Nehmen wir außerdem an, dass wir bereits über GraphQL konfiguriert. Wir möchten dem Kunden die Möglichkeit geben, eine Anfrage in der folgenden Struktur zu stellen:

{
 allZoos : {
    zoo: {
      Name:
      Stadt:
      Tiere: {
        ...
      }
    }
  }
}

Was anstelle der drei Punkte zu setzen ist, um die fehlenden Informationen zu erhalten, werden wir später herausfinden.

Umsetzung

Im Folgenden werde ich die zur Erreichung dieses Ziels erforderlichen Schritte erläutern.

Hinzufügen einer Abfrage zu QueryType

Zunächst muss definiert werden, was genau die Abfrage allZoos bedeutet. Zu diesem Zweck müssen wir die Dateiapp/graphql/types/query_type.rb und definieren Sie die Abfrage:

   Modul Typen
      Klasse QueryType < Types::BaseObject
       Feld :all_zoos, [Types::ZooType], null: false

       def all_zoos
          Zoo.alle
       end
    end
 end

Die Abfrage ist bereits definiert. Nun ist es an der Zeit, die Rückgabetypen zu definieren.

Definition der Typen

Der erste erforderliche Typ ist ZooType. Definieren wir ihn in der Datei app/graphql/types/ zoo_type.rb:

Modul Typen
  Klasse ZooType < Typen::BaseObject
    Feld :name, String, null: false
    feld :stadt, String, null: false
    feld :tiere, [Typen::TierTyp], null: false
  end
end

Nun ist es an der Zeit, den Typ AnimalType zu definieren:

Modul Typen
  Klasse AnimalType < Types::BaseUnion
   mögliche_Typen ElefantTyp, KatzeTyp, HundTyp

     def self.resolve_type(obj, ctx)
       if obj.is_a?(Elefant)
          ElefantTyp
       elsif obj.is_a?(Katze)
         CatType
       elsif obj.is_a?(Hund)
        HundTyp
      end
    end
  end
end

Was sehen wir in der Code oben?

  1. Der AnimalType erbt von Typen::BaseUnion.
  2. Wir müssen alle Typen auflisten, die eine bestimmte Gewerkschaft bilden können.
    3. wir überschreiben die Funktion self.resolve_object(obj, ctx),die den Typ eines bestimmten Objekts zurückgeben muss.

Der nächste Schritt besteht darin, die Tierarten zu definieren. Wir wissen jedoch, dass einige Felder für alle Tiere gleich sind. Nehmen wir sie in den Typ AnimalInterface auf:

Modul Typen
  modul AnimalInterface
    include Typen::BaseInterface

    feld :name, String, null: false
    feld :alter, Ganzzahl, null: false
  end
end

Anhand dieser Schnittstelle können wir nun die einzelnen Tierarten definieren:

Modul Typen
  Klasse ElefantTyp < Types::BaseObject
    implementiert Types::AnimalInterface

    Feld :trunk_length, Float, null: false
  end
end

Modul Typen
  Klasse CatType < Types::BaseObject
   implementiert Types::AnimalInterface

   Feld :hair_type, String, null: false
  end
end

Modul Typen
  Klasse DogType < Types::BaseObject
    implementiert Types::AnimalInterface

     Feld :Rasse, String, null: false
  end
end

Das war's! Fertig! Eine letzte Frage: Wie können wir das, was wir auf der Kundenseite gemacht haben, nutzen?

Erstellung der Abfrage

{
 allZoos : {
   zoo: {
      Name:
      Stadt:
      Tiere: {
        __typenname

        ... on ElefantTyp {
          Name
          Alter
          rüsselLänge
        }

         ... on CatType {
          Name
          Alter
          hairType
         }
         ... on DogType {
          Name
          Alter
          Rasse
         }
       }
     }
   }
 }

Wir können hier ein zusätzliches __typename-Feld verwenden, das den genauen Typ eines bestimmten Elements zurückgibt (z. B. CatType). Wie sieht eine Beispielantwort aus?

{
  "allZoos": [

   {
      "name": "Natura Artis Magistra",
      "Stadt": "Amsterdam",
      "Tiere": [
        {
          "__typenname": "ElefantTyp"
          "name": "Franco",
          "Alter": 28,
          "trunkLength": 9.27
         },
         {
         "__typenname": "DogType"
         "name": "Jack",
         "Alter": 9,
         "Rasse": "Jack Russell Terrier"
        },
      ]
    }
  ]
} 

Analyse

Ein Nachteil dieses Ansatzes ist offensichtlich. In der Abfrage müssen wir bei jedem Typ den Namen und das Alter eingeben, obwohl wir wissen, dass alle Tiere diese Felder haben. Dies ist nicht weiter störend, wenn die Sammlung völlig unterschiedliche Objekte enthält. In diesem Fall haben die Tiere jedoch fast alle Felder gemeinsam. Kann das irgendwie verbessert werden?

Ja, natürlich! Wir nehmen die erste Änderung in der Datei vor app/graphql/types/zoo_type.rb:

Modul Typen
  Klasse ZooType < Typen::BaseObject
    Feld :name, String, null: false
    feld :stadt, String, null: false
    feld :tiere, [Types::AnimalInterface], null: false
  end
end

Wir brauchen nicht mehr die Vereinigung, die wir vorher definiert haben. Wir ändern Typen::AnimalType zu Typen::AnimalInterface.

Der nächste Schritt besteht darin, eine Funktion hinzuzufügen, die einen Typ von Typen :: AnimalInterface und fügen Sie auch eine Liste von orphan_types hinzu, also Typen, die nie direkt verwendet werden:

Modul Typen
  modul AnimalInterface
    include Typen::BaseInterface

   feld :name, String, null: false
   feld :alter, Ganzzahl, null: false

   definition_methods do
      def resolve_type(obj, ctx)
        if obj.is_a?(Elefant)
          ElefantTyp
        elsif obj.is_a?(Katze)
          CatType
        elsif obj.is_a?(Hund)
          HundTyp
        end
      end
    end
    orphan_types Typen::ElefantTyp, Typen::KatzeTyp, Typen::HundTyp
  end
end

Dank dieses einfachen Verfahrens hat die Abfrage eine weniger komplexe Form:

{
  allZoos : {
   zoo: {
      Name:
      Stadt:
      Tiere: {
        __typenname
        Name
        Alter

       ... on ElefantTyp {
          RüsselLänge

       }
       ... on CatType {
          HaarTyp

       }
       ... on DogType {
          Rasse

        }
      }
    }
  }
}

Zusammenfassung

GraphQL ist eine wirklich großartige Lösung. Wenn Sie sie noch nicht kennen, probieren Sie sie aus. Glauben Sie mir, das ist es wert. Sie leistet großartige Arbeit bei der Lösung von Problemen, die z. B. bei REST-APIs auftreten. Wie ich oben gezeigt habe, Polymorphismus ist kein wirkliches Hindernis für sie. Ich habe zwei Methoden vorgestellt, um das Problem zu lösen.
Zur Erinnerung:

  • Wenn Sie mit einer Liste von Objekten mit einer gemeinsamen Basis oder einer gemeinsamen Schnittstelle arbeiten, verwenden Sie die Schnittstellen,
  • Wenn Sie mit einer Liste von Objekten mit einer anderen Struktur arbeiten, verwenden Sie eine andere Schnittstelle - verwenden Sie die Union

Mehr lesen

GraphQL Ruby. Wie sieht es mit der Leistung aus?

Eisenbahnen und andere Transportmittel

Rails-Entwicklung mit TMUX, Vim, Fzf + Ripgrep

Ähnliche Artikel

Software-Entwicklung

Zukunftssichere Web-Apps bauen: Einblicke vom The Codest-Expertenteam

Entdecken Sie, wie sich The Codest bei der Erstellung skalierbarer, interaktiver Webanwendungen mit Spitzentechnologien auszeichnet, die nahtlose Benutzererfahrungen auf allen Plattformen bieten. Erfahren Sie, wie unsere Expertise die digitale Transformation und...

DAS SCHÖNSTE
Software-Entwicklung

Top 10 Softwareentwicklungsunternehmen in Lettland

Erfahren Sie in unserem neuesten Artikel mehr über die besten Softwareentwicklungsunternehmen Lettlands und ihre innovativen Lösungen. Entdecken Sie, wie diese Technologieführer Ihr Unternehmen voranbringen können.

thecodest
Enterprise & Scaleups Lösungen

Grundlagen der Java-Softwareentwicklung: Ein Leitfaden für erfolgreiches Outsourcing

Entdecken Sie diesen wichtigen Leitfaden zum erfolgreichen Outsourcing der Java-Softwareentwicklung, um die Effizienz zu steigern, auf Fachwissen zuzugreifen und den Projekterfolg mit The Codest voranzutreiben.

thecodest
Software-Entwicklung

Der ultimative Leitfaden für Outsourcing in Polen

Der Anstieg des Outsourcings in Polen wird durch wirtschaftliche, bildungspolitische und technologische Fortschritte angetrieben, die das IT-Wachstum und ein unternehmensfreundliches Klima fördern.

TheCodest
Enterprise & Scaleups Lösungen

Der vollständige Leitfaden für IT-Audit-Tools und -Techniken

IT-Audits gewährleisten sichere, effiziente und gesetzeskonforme Systeme. Erfahren Sie mehr über ihre Bedeutung, indem Sie den vollständigen Artikel lesen.

Der Codest
Jakub Jakubowicz CTO & Mitbegründer

Abonnieren Sie unsere Wissensdatenbank und bleiben Sie auf dem Laufenden über das Fachwissen aus dem IT-Sektor.

    Über uns

    The Codest - Internationales Software-Unternehmen mit technischen Zentren in Polen.

    Vereinigtes Königreich - Hauptsitz

    • Büro 303B, 182-184 High Street North E6 2JA
      London, England

    Polen - Lokale Tech-Hubs

    • Fabryczna Office Park, Aleja
      Pokoju 18, 31-564 Kraków
    • Brain Embassy, Konstruktorska
      11, 02-673 Warszawa, Polen

      Der Codest

    • Startseite
    • Über uns
    • Dienstleistungen
    • Fallstudien
    • Gewusst wie
    • Karriere
    • Wörterbuch

      Dienstleistungen

    • IT-Beratung
    • Software-Entwicklung
    • Backend-Softwareentwicklung
    • Frontend-Softwareentwicklung
    • Staff Augmentation
    • Backend-Entwickler
    • Cloud-Ingenieure
    • Daten-Ingenieure
    • Andere
    • QS-Ingenieure

      Ressourcen

    • Fakten und Mythen über die Zusammenarbeit mit einem externen Softwareentwicklungspartner
    • Aus den USA nach Europa: Warum entscheiden sich amerikanische Start-ups für eine Verlagerung nach Europa?
    • Tech Offshore Development Hubs im Vergleich: Tech Offshore Europa (Polen), ASEAN (Philippinen), Eurasien (Türkei)
    • Was sind die größten Herausforderungen für CTOs und CIOs?
    • Der Codest
    • Der Codest
    • Der Codest
    • Privacy policy
    • Website terms of use

    Urheberrecht © 2025 von The Codest. Alle Rechte vorbehalten.

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