window.pipedriveLeadboosterConfig = { base: 'leadbooster-chat.pipedrive.com', companyId: 11580370, playbookUuid: '22236db1-6d50-40c4-b48f-8b11262155be', version: 2, } ;(function () { var w = finestra if (w.LeadBooster) { console.warn('LeadBooster esiste già') } 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 }) }, } } })() Polimorfismo in Ruby e GraphQL - The Codest
The Codest
  • Chi siamo
  • Servizi
    • Sviluppo di software
      • Sviluppo Frontend
      • Sviluppo backend
    • Staff Augmentation
      • Sviluppatori Frontend
      • Sviluppatori backend
      • Ingegneri dei dati
      • Ingegneri del cloud
      • Ingegneri QA
      • Altro
    • Consulenza
      • Audit e consulenza
  • Industrie
    • Fintech e banche
    • E-commerce
    • Adtech
    • Tecnologia della salute
    • Produzione
    • Logistica
    • Automotive
    • IOT
  • Valore per
    • CEO
    • CTO
    • Responsabile della consegna
  • Il nostro team
  • Case Studies
  • Sapere come
    • Blog
    • Incontri
    • Webinar
    • Risorse
Carriera Contattate
  • Chi siamo
  • Servizi
    • Sviluppo di software
      • Sviluppo Frontend
      • Sviluppo backend
    • Staff Augmentation
      • Sviluppatori Frontend
      • Sviluppatori backend
      • Ingegneri dei dati
      • Ingegneri del cloud
      • Ingegneri QA
      • Altro
    • Consulenza
      • Audit e consulenza
  • Valore per
    • CEO
    • CTO
    • Responsabile della consegna
  • Il nostro team
  • Case Studies
  • Sapere come
    • Blog
    • Incontri
    • Webinar
    • Risorse
Carriera Contattate
Freccia indietro TORNA INDIETRO
2022-01-13
Sviluppo di software

Polimorfismo in Ruby e GraphQL

Lukasz Brzeszcz

In questo articolo presenterò l'uso del polimorfismo in GraphQL. Prima di iniziare, però, vale la pena ricordare cosa sono il polimorfismo e GraphQL.

Polimorfismo

Polimorfismo è un componente chiave di programmazione orientata agli oggetti. Per semplificare le cose, si basa sul fatto che oggetti di classi diverse hanno accesso alla stessa interfaccia, il che significa che possiamo aspettarci da ciascuno di essi la stessa funzionalità, ma non necessariamente implementata nello stesso modo. In Sviluppatori Ruby può ottenere polimorfismo in tre modi:

Eredità

Eredità consiste nel creare una classe madre e delle classi figlie (cioè che ereditano dalla classe madre). Le sottoclassi ricevono le funzionalità della classe madre e consentono anche di modificare e aggiungere funzionalità.

Esempio:

classe Documento
  attr_reader :name
fine

classe PDFDocument < Documento
  def estensione
    :pdf
  fine
fine

classe ODTDocument < Documento
  def estensione
    :odt
  fine
fine

Moduli

Moduli in Rubino hanno molti usi. Uno di questi è rappresentato dai mixin (per saperne di più sui mixin, vedere la sezione La scomposizione definitiva: Ruby vs. Python). I mixin in Ruby possono essere usati in modo simile alle interfacce in altri linguaggi di programmazione (ad esempio, in Java), per esempio, si possono definire in essi metodi comuni agli oggetti che conterranno un determinato mixin. È buona norma includere nei moduli metodi di sola lettura, quindi metodi che non modifichino lo stato dell'oggetto.

Esempio:

modulo Imponibile
  def imposta

     prezzo * 0,23
  fine
fine

classe Auto
  include Taxable
 attr_reader :price
fine

classe Libro
  include Taxable

 attr_reader :price
fine

Dattilografia per anatre

Questa è una delle caratteristiche principali dei linguaggi tipizzati dinamicamente. Il nome deriva dal famoso test: se sembra un'anatra, nuota come un'anatra e starnazza come un'anatra, allora probabilmente è un'anatra. Il programmatore non deve interessarsi a quale classe appartiene l'oggetto dato. Ciò che conta sono i metodi che possono essere richiamati su questo oggetto.

Utilizzando le classi definite nell'esempio precedente:

classe Auto
  attr_reader :price

 def initialize(prezzo)
    @prezzo = prezzo
   fine
fine

classe Libro
  attr_reader :price

 def initialize(prezzo)
    @prezzo = prezzo
  fine
fine

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

[auto, libro].map(&:prezzo

GrapQL

GraphQL è un linguaggio di interrogazione relativamente nuovo per le API. Tra i suoi vantaggi c'è il fatto che ha una sintassi molto semplice e, inoltre, è il cliente a decidere cosa vuole ottenere esattamente, poiché ogni cliente riceve esattamente ciò che desidera e nient'altro.

Esempio di query in GraphQL:

{
  allUsers {
     utenti {
        id
        login
        email

       }
     }
   }

Esempio di risposta:

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

Probabilmente questo è tutto quello che c'è da sapere al momento. Quindi, veniamo al punto.

Presentazione del problema

Per capire meglio il problema e la sua soluzione, creiamo un esempio. Sarebbe bene che l'esempio fosse originale e abbastanza concreto. Uno di quelli che ognuno di noi può incontrare un giorno. Che ne dite di... animali? Sì! Ottima idea!

polimorfismo di ruby e grapql - animali

Supponiamo di avere un'applicazione backend scritta in Ruby on Rails. È già adattato per gestire lo schema precedente. Supponiamo inoltre di avere già GraphQL configurato. Vogliamo consentire al cliente di effettuare una richiesta all'interno della seguente struttura:

{
 allZoos : {
    zoo: {
      nome
      città
      animali: {
        ...
      }
    }
  }
}

Cosa si dovrebbe mettere al posto dei tre punti per ottenere le informazioni mancanti - lo scopriremo più avanti.

Attuazione

Di seguito presenterò i passi necessari per raggiungere l'obiettivo.

Aggiunta di una query a QueryType

Per prima cosa, è necessario definire il significato esatto della query allZoos. Per farlo, occorre visitare il fileapp/graphql/types/query_type.rb e definire la query:

   modulo Tipi
      classe QueryType < Types::BaseObject
       field :all_zoos, [Types::ZooType], null: false

       def tutti_zoo
          Zoo.all
       fine
    fine
 fine

La query è già definita. Ora è il momento di definire i tipi di ritorno.

Definizione dei tipi

Il primo tipo richiesto sarà ZooType. Definiamolo nel file app/graphql/types/ zoo_type.rb:

modulo Tipi
  classe ZooType < Types::BaseObject
    campo :name, String, null: false
    campo :city, Stringa, null: false
    campo :animals, [Types::AnimalType], null: false
  fine
fine

Ora è il momento di definire il tipo AnimalType:

modulo Tipi
  classe AnimalType < Types::BaseUnion
   possibili_tipi ElefanteTipo, GattoTipo, CaneTipo

     def self.resolve_type(obj, ctx)
       if obj.is_a?(Elefante)
          Tipo Elefante
       elsif obj.is_a?(Cat)
         Tipo Gatto
       elsif obj.is_a?(Dog)
        Tipo Cane
      fine
    fine
  fine
fine

Cosa vediamo nel codice sopra?

  1. AnimalType eredita da Tipi::BaseUnion.
  2. Dobbiamo elencare tutti i tipi che possono comporre una determinata unione.
    3.Sovrascriviamo la funzione self.resolve_object(obj, ctx),che deve restituire il tipo di un dato oggetto.

Il passo successivo consiste nel definire i tipi di animali. Tuttavia, sappiamo che alcuni campi sono comuni a tutti gli animali. Includiamoli nel tipo AnimalInterface:

modulo Tipi
  modulo AnimalInterface
    include Types::BaseInterface

    campo :name, String, null: false
    campo :age, Integer, null: false
  fine
fine

Avendo questa interfaccia, possiamo procedere a definire i tipi di animali specifici:

modulo Tipi
  classe ElephantType < Types::BaseObject
    implementa Types::AnimalInterface

    campo :lunghezza_tronco, Float, null: false
  fine
fine

modulo Tipi
  classe CatType < Types::BaseObject
   implementa Types::AnimalInterface

   campo :hair_type, String, null: false
  fine
fine

modulo Tipi
  classe DogType < Types::BaseObject
    implementa Types::AnimalInterface

     campo :razza, String, null: false
  fine
fine

Ecco fatto! Pronti! Un'ultima domanda: come possiamo utilizzare ciò che abbiamo fatto dal lato del cliente?

Creazione della query

{
 allZoos : {
   zoo: {
      nome
      città
      animali: {
        __typename

        ... su ElephantType {
          nome
          età
          lunghezza della proboscide
        }

         ... su CatType {
          nome
          età
          tipo di pelo
         }
         ... su DogType {
          nome
          età
          razza
         }
       }
     }
   }
 }

Possiamo usare un campo aggiuntivo __typename, che restituirà il tipo esatto di un dato elemento (per esempio, CatType). Come sarà una risposta di esempio?

{
  "allZoos": [

   {
      "name": "Natura Artis Magistra",
      "città": "Amsterdam",
      "animali": [
        {
          "__typename": "ElephantType"
          "nome": "Franco",
          "età": 28,
          "lunghezza della proboscide": 9.27
         },
         {
         "__typename": "DogType"
         "nome": "Jack",
         "età": 9,
         "razza": "Jack Russell Terrier"
        },
      ]
    }
  ]
} 

Analisi

Questo approccio presenta uno svantaggio. Nella query, dobbiamo inserire il nome e l'età per ogni tipo, anche se sappiamo che tutti gli animali hanno questi campi. Questo non è un problema quando la collezione contiene oggetti completamente diversi. In questo caso, però, gli animali condividono quasi tutti i campi. Si può migliorare in qualche modo?

Naturalmente! Apportiamo la prima modifica al file app/graphql/types/zoo_type.rb:

modulo Tipi
  classe ZooType < Types::BaseObject
    campo :name, String, null: false
    campo :city, Stringa, null: false
    campo :animals, [Types::AnimalInterface], null: false
  fine
fine

Non abbiamo più bisogno dell'unione che abbiamo definito prima. Cambiamo Tipi::AnimalType a Types::AnimalInterface.

Il passo successivo è aggiungere una funzione che restituisca un tipo da Tipi :: Interfaccia Animale e aggiungere anche un elenco di tipi orfani, cioè di tipi che non vengono mai utilizzati direttamente:

modulo Tipi
  modulo AnimalInterface
    include Types::BaseInterface

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

   definizione_metodi do
      def resolve_type(obj, ctx)
        if obj.is_a?(Elefante)
          Tipo Elefante
        elsif obj.is_a?(Cat)
          Tipo Gatto
        elsif obj.is_a?(Dog)
          Tipo Cane
        fine
      fine
    fine
    orphan_types Types::ElephantType, Types::CatType, Types::DogType
  fine
fine

Grazie a questa semplice procedura, la query ha una forma meno complessa:

{
  allZoos : {
   zoo: {
      nome
      città
      animali: {
        __typename
        nome
        età

       ... su ElephantType {
          lunghezza della proboscide

       }
       ... su CatType {
          tipoCapelli

       }
       ... su DogType {
          razza

        }
      }
    }
  }
}

Sintesi

GraphQL è una soluzione davvero eccezionale. Se non la conoscete ancora, provatela. Credetemi, ne vale la pena. Fa un ottimo lavoro nel risolvere i problemi che si presentano, ad esempio, nelle API REST. Come ho mostrato sopra, polimorfismo non è un vero e proprio ostacolo. Ho presentato due metodi per affrontarlo.
Promemoria:

  • Se si opera su un elenco di oggetti con una base comune o un'interfaccia comune, utilizzare le interfacce,
  • Se si opera su un elenco di oggetti con una struttura diversa, si deve utilizzare un'interfaccia diversa: utilizzare l'unione

Per saperne di più

GraphQL Ruby. E le prestazioni?

Rotaie e altri mezzi di trasporto

Sviluppo di Rails con TMUX, Vim, Fzf + Ripgrep

Articoli correlati

Sviluppo di software

Costruire applicazioni web a prova di futuro: le intuizioni del team di esperti di The Codest

Scoprite come The Codest eccelle nella creazione di applicazioni web scalabili e interattive con tecnologie all'avanguardia, offrendo esperienze utente senza soluzione di continuità su tutte le piattaforme. Scoprite come la nostra esperienza favorisce la trasformazione digitale e il business...

IL CANCRO
Sviluppo di software

Le 10 principali aziende di sviluppo software con sede in Lettonia

Scoprite le migliori aziende di sviluppo software della Lettonia e le loro soluzioni innovative nel nostro ultimo articolo. Scoprite come questi leader tecnologici possono aiutarvi a migliorare la vostra attività.

thecodest
Soluzioni per aziende e scaleup

Essenziali di sviluppo software Java: Guida all'outsourcing di successo

Esplorate questa guida essenziale sullo sviluppo di software Java con successo outsourcing per migliorare l'efficienza, accedere alle competenze e guidare il successo del progetto con The Codest.

thecodest
Sviluppo di software

La guida definitiva all'outsourcing in Polonia

L'aumento di outsourcing in Polonia è guidato dai progressi economici, educativi e tecnologici, che favoriscono la crescita dell'IT e un clima favorevole alle imprese.

IlCodesto
Soluzioni per aziende e scaleup

Guida completa agli strumenti e alle tecniche di audit IT

Gli audit IT garantiscono sistemi sicuri, efficienti e conformi. Per saperne di più sulla loro importanza, leggete l'articolo completo.

The Codest
Jakub Jakubowicz CTO e cofondatore

Iscrivetevi alla nostra knowledge base e rimanete aggiornati sulle competenze del settore IT.

    Chi siamo

    The Codest - Società internazionale di sviluppo software con centri tecnologici in Polonia.

    Regno Unito - Sede centrale

    • Ufficio 303B, 182-184 High Street North E6 2JA
      Londra, Inghilterra

    Polonia - Poli tecnologici locali

    • Parco uffici Fabryczna, Aleja
      Pokoju 18, 31-564 Cracovia
    • Ambasciata del cervello, Konstruktorska
      11, 02-673 Varsavia, Polonia

      The Codest

    • Casa
    • Chi siamo
    • Servizi
    • Case Studies
    • Sapere come
    • Carriera
    • Dizionario

      Servizi

    • Consulenza
    • Sviluppo di software
    • Sviluppo backend
    • Sviluppo Frontend
    • Staff Augmentation
    • Sviluppatori backend
    • Ingegneri del cloud
    • Ingegneri dei dati
    • Altro
    • Ingegneri QA

      Risorse

    • Fatti e miti sulla collaborazione con un partner esterno per lo sviluppo di software
    • Dagli Stati Uniti all'Europa: Perché le startup americane decidono di trasferirsi in Europa
    • Confronto tra gli hub di sviluppo Tech Offshore: Tech Offshore Europa (Polonia), ASEAN (Filippine), Eurasia (Turchia)
    • Quali sono le principali sfide di CTO e CIO?
    • The Codest
    • The Codest
    • The Codest
    • Privacy policy
    • Condizioni di utilizzo del sito web

    Copyright © 2025 di The Codest. Tutti i diritti riservati.

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