The Codest
  • O nás
  • Služby
    • Vývoj softwaru
      • Vývoj frontendů
      • Vývoj backendu
    • Staff Augmentation
      • Vývojáři frontendů
      • Vývojáři backendu
      • Datoví inženýři
      • Cloudoví inženýři
      • Inženýři QA
      • Další
    • To Advisory
      • Audit a poradenství
  • Odvětví
    • Fintech a bankovnictví
    • E-commerce
    • Adtech
    • Healthtech
    • Výroba
    • Logistika
    • Automobilový průmysl
    • IOT
  • Hodnota za
    • CEO
    • CTO
    • Manažer dodávek
  • Náš tým
  • Case Studies
  • Vědět jak
    • Blog
    • Setkání
    • Webové semináře
    • Zdroje
Kariéra Spojte se s námi
  • O nás
  • Služby
    • Vývoj softwaru
      • Vývoj frontendů
      • Vývoj backendu
    • Staff Augmentation
      • Vývojáři frontendů
      • Vývojáři backendu
      • Datoví inženýři
      • Cloudoví inženýři
      • Inženýři QA
      • Další
    • To Advisory
      • Audit a poradenství
  • Hodnota za
    • CEO
    • CTO
    • Manažer dodávek
  • Náš tým
  • Case Studies
  • Vědět jak
    • Blog
    • Setkání
    • Webové semináře
    • Zdroje
Kariéra Spojte se s námi
Šipka zpět ZPĚT
2022-01-13
Vývoj softwaru

Polymorfismus v jazyce Ruby a GraphQL

Lukasz Brzeszcz

V tomto článku představím použití polymorfismu v jazyce GraphQL. Než však začnu, je vhodné připomenout, co polymorfismus a GraphQL jsou.

Polymorfismus

Polymorfismus je klíčovou součástí objektově orientované programování. Zjednodušeně řečeno, vychází z toho, že objekty různých tříd mají přístup ke stejnému rozhraní, což znamená, že od každého z nich můžeme očekávat stejnou funkčnost, která však nemusí být nutně implementována stejným způsobem. Na adrese Ruby vývojáři může získat polymorfismus třemi způsoby:

Dědictví

Dědictví spočívá ve vytvoření nadřazené třídy a podřazených tříd (tj. dědičných od nadřazené třídy). Podtřídy přebírají funkčnost rodičovské třídy a také umožňují měnit a přidávat funkčnost.

Příklad:

třída Document
  attr_reader :name
end

třída PDFDocument < Document
  def rozšíření
    :pdf
  end
end

třída ODTDocument < Dokument
  def rozšíření
    :odt
  end
end

Moduly

Moduly v Ruby mají mnohostranné využití. Jedním z nich jsou mixiny (více o mixinech se dočtete v článku Konečné rozdělení: Ruby vs. Python). Mixiny v jazyce Ruby lze používat podobně jako rozhraní v jiných programovacích jazycích (např. v Java), můžete v nich například definovat metody společné pro objekty, které budou obsahovat daný mixin. Dobrou praxí je zařazovat do modulů metody určené pouze pro čtení, tedy metody, které nebudou měnit stav tohoto objektu.

Příklad:

modul Zdanitelné
  def tax

     cena * 0,23
  end
end

třída Auto
  include Taxable
 attr_reader :price
end

třída Book
  include Taxable

 attr_reader :price
end

Psaní na klávesnici Duck

To je jedna z klíčových vlastností dynamicky typovaných jazyků. Název pochází ze známého testu, že pokud to vypadá jako kachna, plave to jako kachna a kváká to jako kachna, pak je to pravděpodobně kachna. Na adrese programátor nemusí zajímat, do které třídy daný objekt patří. Důležité jsou metody, které lze nad tímto objektem volat.

Pomocí tříd definovaných ve výše uvedeném příkladu:

třída Auto
  attr_reader :price

 def inicializovat(cena)
    @price = price
   end
end

třída Book
  attr_reader :price

 def inicializovat(cena)
    @price = price
  end
end

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

[car, book].map(&:price

GrapQL

GraphQL je relativně nový dotazovací jazyk pro rozhraní API. Mezi jeho výhody patří to, že má velmi jednoduchou syntaxi a navíc klient rozhoduje, co přesně chce získat, protože každý zákazník dostane přesně to, co chce, a nic jiného.

Ukázka dotazu v GraphQL:

{
  allUsers {
     users {
        id
        login
        email

       }
     }
   }

Vzorová odpověď:

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

To je asi vše, co v tuto chvíli potřebujeme vědět. Přejděme tedy k věci.

Představení problému

Abychom co nejlépe pochopili problém a jeho řešení, vytvoříme si příklad. Bylo by dobré, kdyby byl příklad originální a zároveň poměrně přízemní. Takový, aby každý z nás se může jednoho dne setkat. Co třeba... zvířata? Ano! Skvělý nápad!

ruby a grapql polymorfismus - zvířata

Předpokládejme, že máme backendovou aplikaci napsanou v jazyce Ruby on Rails. Je již přizpůsoben pro zpracování výše uvedeného schématu. Předpokládejme také, že již máme GraphQL konfigurováno. Chceme klientovi umožnit zadat dotaz v následující struktuře:

{
 allZoos : {
    zoo: {
      name
      město
      zvířata: {
        ...
      }
    }
  }
}

Co je třeba vložit místo tří teček, abychom získali chybějící informace - zjistíme později.

Provádění

Níže uvádím kroky potřebné k dosažení cíle.

Přidání dotazu do QueryType

Nejprve je třeba definovat, co přesně znamená dotaz allZoos. Za tímto účelem musíme navštívit souborapp/graphql/types/query_type.rb a definujte dotaz:

   Typy modulů
      třída QueryType < Types::BaseObject
       field :all_zoos, [Types::ZooType], null: false

       def all_zoos
          Zoo.all
       end
    end
 end

Dotaz je již definován. Nyní je čas definovat návratové typy.

Definice typů

Prvním požadovaným typem bude ZooType. Definujme jej v souboru app/graphql/types/ zoo_type.rb:

Typy modulů
  class ZooType < Types::BaseObject
    field :name, String, null: false
    field :city, String, null: false
    pole :animals, [Types::AnimalType], null: false
  end
end

Nyní je čas definovat typ AnimalType:

Typy modulů
  třída 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)
         CatType
       elsif obj.is_a?(Dog)
        DogType
      end
    end
  end
end

Co vidíme v kód výše?

  1. AnimalType dědí od Types::BaseUnion.
  2. Musíme uvést všechny typy, které mohou tvořit danou unii.
    3.Přepíšeme funkci self.resolve_object(obj, ctx),který musí vrátit typ daného objektu.

Dalším krokem je definování typů zvířat. Víme však, že některá pole jsou společná všem živočichům. Zařaďme je do typu AnimalInterface:

Typy modulů
  modul AnimalInterface
    include Types::BaseInterface

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

Po vytvoření tohoto rozhraní můžeme přejít k definování typů konkrétních zvířat:

Typy modulů
  class ElephantType < Types::BaseObject
    implementuje Types::AnimalInterface

    field :trunk_length, Float, null: false
  end
end

modul Typy
  class CatType < Types::BaseObject
   implementuje Types::AnimalInterface

   field :hair_type, String, null: false
  end
end

modul Typy
  class DogType < Types::BaseObject
    implementuje Types::AnimalInterface

     field :breed, String, null: false
  end
end

A je to! Připraveno! Poslední otázka: Jak můžeme využít to, co jsme udělali na straně klienta?

Sestavení dotazu

{
 allZoos : {
   zoo: {
      name
      město
      zvířata: {
        __typename

        ... on ElephantType {
          name
          věk
          trunkLength
        }

         ... on CatType {
          name
          age
          hairType
         }
         ... on DogType {
          name
          age
          plemeno
         }
       }
     }
   }
 }

Zde můžeme použít další pole __typename, které vrátí přesný typ daného prvku (např. CatType). Jak bude vypadat ukázková odpověď?

{
  "allZoos": [

   {
      "name": "Natura Artis Magistra",
      "city": "Amsterdam",
      "animals": [
        {
          "__typename": "ElephantType"
          "name": "Franco",
          "age": 28,
          "trunkLength": 9.27
         },
         {
         "__typename": "DogType"
         "name": "Jack",
         "age": 9,
         "plemeno": "Jack Russell teriér"
        },
      ]
    }
  ]
} 

Analýza

Jeden nedostatek tohoto přístupu je zřejmý. V dotazu musíme u každého typu zadat jméno a věk, přestože víme, že tato pole mají všechna zvířata. To však nevadí, pokud kolekce obsahuje zcela odlišné objekty. V tomto případě však mají zvířata téměř všechna pole společná. Dá se to nějak vylepšit?

Samozřejmě! Provedeme první změnu v souboru app/graphql/types/zoo_type.rb:

Typy modulů
  class ZooType < Types::BaseObject
    field :name, String, null: false
    field :city, String, null: false
    pole :animals, [Types::AnimalInterface], null: false
  end
end

Dříve definovanou unii již nepotřebujeme. Změníme Types::AnimalType na Types::AnimalInterface.

Dalším krokem je přidání funkce, která vrací typ z Typy :: AnimalInterface a také přidat seznam orphan_types, tedy typů, které se nikdy přímo nepoužívají:

Typy modulů
  modul AnimalInterface
    include Types::BaseInterface

   field :name, String, null: false
   field :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)
          DogType
        end
      end
    end
    orphan_types Types::ElephantType, Types::CatType, Types::DogType
  end
end

Díky tomuto jednoduchému postupu má dotaz méně složitý tvar:

{
  allZoos : {
   zoo: {
      name
      město
      zvířata: {
        __typename
        name
        age

       ... on ElephantType {
          trunkLength

       }
       ... on CatType {
          hairType

       }
       ... on DogType {
          plemeno

        }
      }
    }
  }
}

Souhrn

GraphQL je opravdu skvělým řešením. Pokud ho ještě neznáte, vyzkoušejte ho. Věřte mi, stojí to za to. Odvádí skvělou práci při řešení problémů objevujících se například v rozhraních REST API. Jak jsem ukázal výše, polymorfismus není pro něj skutečnou překážkou. Představil jsem dvě metody, jak ji řešit.
Připomínáme:

  • Pokud pracujete se seznamem objektů se společným základem nebo společným rozhraním - použijte rozhraní,
  • Pokud pracujete se seznamem objektů s jinou strukturou, použijte jiné rozhraní - použijte union.

Přečtěte si více

GraphQL Ruby. Jak je to s výkonem?

Kolejnice a další dopravní prostředky

Vývoj Rails pomocí TMUX, Vim, Fzf + Ripgrep

Související články

Ilustrace zdravotnické aplikace pro chytré telefony s ikonou srdce a rostoucím zdravotním grafem, označená logem The Codest, která představuje digitální zdraví a řešení HealthTech.
Vývoj softwaru

Softwarové vybavení pro zdravotnictví: a případy použití

Nástroje, na které se dnes zdravotnické organizace spoléhají, se v ničem nepodobají papírovým kartám z doby před desítkami let. zdravotnický software dnes podporuje zdravotnické systémy, péči o pacienty a moderní poskytování zdravotní péče v klinických a...

NEJKRÁSNĚJŠÍ
Abstraktní ilustrace klesajícího sloupcového grafu se stoupající šipkou a zlatou mincí symbolizující efektivitu nákladů nebo úspory. V levém horním rohu se zobrazuje logo The Codest se sloganem "In Code We Trust" na světle šedém pozadí.
Vývoj softwaru

Jak rozšířit tým vývojářů bez ztráty kvality produktu

Zvětšujete svůj vývojový tým? Zjistěte, jak růst, aniž byste museli obětovat kvalitu produktu. Tento průvodce se zabývá příznaky, že je čas na škálování, strukturou týmu, najímáním zaměstnanců, vedením a nástroji - a také tím, jak může The Codest...

NEJKRÁSNĚJŠÍ
Vývoj softwaru

Vytváření webových aplikací odolných vůči budoucnosti: postřehy týmu odborníků The Codest

Zjistěte, jak společnost The Codest vyniká při vytváření škálovatelných, interaktivních webových aplikací pomocí nejmodernějších technologií, které poskytují bezproblémové uživatelské prostředí na všech platformách. Zjistěte, jak naše odborné znalosti podporují digitální transformaci a obchodní...

NEJKRÁSNĚJŠÍ
Vývoj softwaru

10 nejlepších lotyšských společností zabývajících se vývojem softwaru

V našem nejnovějším článku se dozvíte o nejlepších lotyšských společnostech zabývajících se vývojem softwaru a jejich inovativních řešeních. Zjistěte, jak mohou tito technologičtí lídři pomoci pozvednout vaše podnikání.

thecodest
Podniková a škálovací řešení

Základy vývoje softwaru v jazyce Java: A Guide to Outsourcing Successfully

Prozkoumejte tuto základní příručku o úspěšném vývoji softwaru outsourcing Java, abyste zvýšili efektivitu, získali přístup k odborným znalostem a dosáhli úspěchu projektu s The Codest.

thecodest

Přihlaste se k odběru naší znalostní databáze a získejte aktuální informace o odborných znalostech z oblasti IT.

    O nás

    The Codest - Mezinárodní společnost zabývající se vývojem softwaru s technologickými centry v Polsku.

    Spojené království - ústředí

    • Kancelář 303B, 182-184 High Street North E6 2JA
      Londýn, Anglie

    Polsko - Místní technologická centra

    • Kancelářský park Fabryczna, Aleja
      Pokoju 18, 31-564 Krakov
    • Brain Embassy, Konstruktorska
      11, 02-673 Varšava, Polsko

      The Codest

    • Home
    • O nás
    • Služby
    • Case Studies
    • Vědět jak
    • Kariéra
    • Slovník

      Služby

    • To Advisory
    • Vývoj softwaru
    • Vývoj backendu
    • Vývoj frontendů
    • Staff Augmentation
    • Vývojáři backendu
    • Cloudoví inženýři
    • Datoví inženýři
    • Další
    • Inženýři QA

      Zdroje

    • Fakta a mýty o spolupráci s externím partnerem pro vývoj softwaru
    • Z USA do Evropy: Proč se americké startupy rozhodly přesídlit do Evropy?
    • Srovnání technických vývojových center v zahraničí: Tech Offshore Evropa (Polsko), ASEAN (Filipíny), Eurasie (Turecko)
    • Jaké jsou hlavní výzvy CTO a CIO?
    • The Codest
    • The Codest
    • The Codest
    • Privacy policy
    • Website terms of use

    Copyright © 2026 by The Codest. Všechna práva vyhrazena.

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