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 υπάρχει ήδη') } 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 }) }, } } })() Πολυμορφισμός στη Ruby και τη GraphQL - The Codest
The Codest
  • Σχετικά με εμάς
  • Υπηρεσίες
    • Ανάπτυξη λογισμικού
      • Ανάπτυξη Frontend
      • Backend Ανάπτυξη
    • Staff Augmentation
      • Frontend Developers
      • Backend Developers
      • Μηχανικοί δεδομένων
      • Μηχανικοί cloud
      • Μηχανικοί QA
      • Άλλα
    • Συμβουλευτική
      • Έλεγχος & Συμβουλευτική
  • Βιομηχανίες
    • Fintech & Τραπεζική
    • E-commerce
    • Adtech
    • Healthtech
    • Κατασκευή
    • Εφοδιαστική
    • Αυτοκίνητο
    • IOT
  • Αξία για
    • CEO
    • CTO
    • Διευθυντής παράδοσης
  • Η ομάδα μας
  • Case Studies
  • Μάθετε πώς
    • Blog
    • Συναντήσεις
    • Διαδικτυακά σεμινάρια
    • Πόροι
Καριέρα Ελάτε σε επαφή
  • Σχετικά με εμάς
  • Υπηρεσίες
    • Ανάπτυξη λογισμικού
      • Ανάπτυξη Frontend
      • Backend Ανάπτυξη
    • Staff Augmentation
      • Frontend Developers
      • Backend Developers
      • Μηχανικοί δεδομένων
      • Μηχανικοί cloud
      • Μηχανικοί QA
      • Άλλα
    • Συμβουλευτική
      • Έλεγχος & Συμβουλευτική
  • Αξία για
    • CEO
    • CTO
    • Διευθυντής παράδοσης
  • Η ομάδα μας
  • Case Studies
  • Μάθετε πώς
    • Blog
    • Συναντήσεις
    • Διαδικτυακά σεμινάρια
    • Πόροι
Καριέρα Ελάτε σε επαφή
Πίσω βέλος GO BACK
2022-01-13
Ανάπτυξη λογισμικού

Πολυμορφισμός στη Ruby και τη GraphQL

Lukasz Brzeszcz

Σε αυτό το άρθρο, θα παρουσιάσω τη χρήση του πολυμορφισμού στην GraphQL. Πριν ξεκινήσω, ωστόσο, αξίζει να υπενθυμίσω τι είναι ο πολυμορφισμός και η GraphQL.

Πολυμορφισμός

Πολυμορφισμός αποτελεί βασικό συστατικό της αντικειμενοστραφής προγραμματισμός. Για να απλοποιήσουμε τα πράγματα, βασίζεται στο γεγονός ότι τα αντικείμενα διαφορετικών κλάσεων έχουν πρόσβαση στην ίδια διεπαφή, πράγμα που σημαίνει ότι μπορούμε να περιμένουμε από καθένα από αυτά την ίδια λειτουργικότητα, αλλά όχι απαραίτητα υλοποιημένη με τον ίδιο τρόπο. Στο Προγραμματιστές Ruby μπορεί να λάβει πολυμορφισμός με τρεις τρόπους:

Κληρονομικότητα

Κληρονομικότητα συνίσταται στη δημιουργία μιας γονικής κλάσης και κλάσεων-παιδιών (δηλαδή, που κληρονομούν από τη γονική κλάση). Οι υποκλάσεις λαμβάνουν τη λειτουργικότητα της γονικής κλάσης και σας επιτρέπουν επίσης να αλλάξετε και να προσθέσετε μια λειτουργικότητα.

Παράδειγμα:

κλάση Document
  attr_reader :name
end

class PDFDocument < Document
  def extension
    :pdf
  end
end

class ODTDocument < Document
  def extension
    :odt
  end
end

Ενότητες

Ενότητες σε Ruby έχουν πολλές χρήσεις. Μία από αυτές είναι τα mixins (διαβάστε περισσότερα για τα mixins στο Η απόλυτη ανάλυση: Python). Τα mixins στη Ruby μπορούν να χρησιμοποιηθούν παρόμοια με τις διασυνδέσεις σε άλλες γλώσσες προγραμματισμού (π.χ. σε Java), για παράδειγμα, μπορείτε να ορίσετε σε αυτές μεθόδους κοινές για τα αντικείμενα που θα περιέχουν ένα συγκεκριμένο mixin. Αποτελεί καλή πρακτική να συμπεριλαμβάνετε μεθόδους μόνο για ανάγνωση στις μονάδες, δηλαδή μεθόδους που δεν θα τροποποιούν την κατάσταση αυτού του αντικειμένου.

Παράδειγμα:

ενότητα Φορολογητέα
  def tax

     τιμή * 0.23
  end
end

κλάση Αυτοκίνητο
  include Taxable
 attr_reader :price
end

class Book
  include Taxable

 attr_reader :price
end

Δακτυλογράφηση πάπιας

Αυτό είναι ένα από τα βασικά χαρακτηριστικά των δυναμικά τυποποιημένων γλωσσών. Το όνομα προέρχεται από το διάσημο τεστ αν μοιάζει με πάπια, κολυμπάει σαν πάπια και λαλεί σαν πάπια, τότε μάλλον είναι πάπια. Το προγραμματιστής δεν χρειάζεται να ενδιαφέρεται για το σε ποια κλάση ανήκει το συγκεκριμένο αντικείμενο. Αυτό που έχει σημασία είναι οι μέθοδοι που μπορούν να κληθούν σε αυτό το αντικείμενο.

Χρησιμοποιώντας τις κλάσεις που ορίζονται στο παραπάνω παράδειγμα:

κλάση Αυτοκίνητο
  attr_reader :price

 def initialize(price)
    @price = price
   end
end

class Book
  attr_reader :price

 def initialize(price)
    @price = price
  end
end

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

[car, book].map(&:price

GrapQL

GraphQL είναι μια σχετικά νέα γλώσσα ερωτημάτων για APIs. Στα πλεονεκτήματά της συγκαταλέγεται το γεγονός ότι έχει πολύ απλή σύνταξη και, επιπλέον, ο πελάτης αποφασίζει τι ακριβώς θέλει να πάρει, καθώς κάθε πελάτης παίρνει ακριβώς αυτό που θέλει και τίποτε άλλο.

Δείγμα ερωτήματος στο GraphQL:

{
  allUsers {
     users {
        id
        login
        email

       }
     }
   }

Δείγμα απάντησης:

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

Αυτό είναι μάλλον το μόνο που χρειάζεται να γνωρίζουμε προς το παρόν. Ας μπούμε λοιπόν στο θέμα.

Παρουσίαση του προβλήματος

Για να κατανοήσουμε καλύτερα το πρόβλημα και τη λύση του, ας δημιουργήσουμε ένα παράδειγμα. Καλό θα ήταν το παράδειγμα να είναι πρωτότυπο και αρκετά προσγειωμένο. Ένα παράδειγμα που ο καθένας μας μπορεί να αντιμετωπίσει κάποια μέρα. Τι θα λέγατε για... ζώα; Ναι! Υπέροχη ιδέα!

πολυμορφισμός ruby και grapql - ζώα

Ας υποθέσουμε ότι έχουμε μια backend εφαρμογή γραμμένη σε Ruby on Rails. Έχει ήδη προσαρμοστεί για να χειριστεί το παραπάνω σχήμα. Ας υποθέσουμε επίσης ότι έχουμε ήδη GraphQL διαμορφωμένο. Θέλουμε να δώσουμε τη δυνατότητα στον πελάτη να κάνει μια έρευνα με την ακόλουθη δομή:

{
 allZoos : {
    zoo: {
      name
      city
      ζώα: {
        ...
      }
    }
  }
}

Τι θα πρέπει να βάλετε αντί για τις τρεις τελείες για να λάβετε τις πληροφορίες που λείπουν - θα το μάθουμε αργότερα.

Εφαρμογή

Παρακάτω θα παρουσιάσω τα βήματα που απαιτούνται για την επίτευξη του στόχου.

Προσθήκη ερώτησης στο QueryType

Πρώτον, πρέπει να ορίσετε τι ακριβώς σημαίνει το ερώτημα allZoos. Για να το κάνουμε αυτό, πρέπει να επισκεφτούμε το αρχείοapp/graphql/types/query_type.rb και ορίστε το ερώτημα:

   ενότητα Τύποι
      class QueryType < Types::BaseObject
       field :all_zoos, [Types::ZooType], null: false

       def all_zoos
          Zoo.all
       end
    end
 end

Το ερώτημα έχει ήδη οριστεί. Τώρα ήρθε η ώρα να ορίσουμε τους τύπους επιστροφής.

Ορισμός των τύπων

Ο πρώτος απαιτούμενος τύπος θα είναι ο ZooType. Ας τον ορίσουμε στο αρχείο app/graphql/types/ zoo_type.rb:

ενότητα Τύποι
  class ZooType < Types::BaseObject
    field :name, String, null: false
    field :city, String, null: false
    field :animals, [Types::AnimalType], null: false
  end
end

Τώρα ήρθε η ώρα να ορίσουμε τον τύπο AnimalType:

ενότητα Τύποι
  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)
         CatType
       elsif obj.is_a?(Dog)
        DogType
      end
    end
  end
end

Τι βλέπουμε στο κωδικός παραπάνω;

  1. Το AnimalType κληρονομεί από το Τύποι::BaseUnion.
  2. Πρέπει να απαριθμήσουμε όλους τους τύπους που μπορούν να αποτελέσουν μια δεδομένη ένωση.
    3.Παρακάμπτουμε τη συνάρτηση self.resolve_object(obj, ctx),η οποία πρέπει να επιστρέφει τον τύπο ενός συγκεκριμένου αντικειμένου.

Το επόμενο βήμα είναι ο καθορισμός των τύπων των ζώων. Ωστόσο, γνωρίζουμε ότι ορισμένα πεδία είναι κοινά για όλα τα ζώα. Ας τα συμπεριλάβουμε στον τύπο AnimalInterface:

ενότητα Τύποι
  module AnimalInterface
    include Types::BaseInterface

    πεδίο :name, String, null: false
    πεδίο :age, Ακέραιος αριθμός, null: false
  end
end

Έχοντας αυτή τη διεπαφή, μπορούμε να προχωρήσουμε στον καθορισμό των τύπων των συγκεκριμένων ζώων:

ενότητα Τύποι
  class ElephantType < Types::BaseObject
    υλοποιεί Types::AnimalInterface

    πεδίο :trunk_length, Float, null: false
  end
end

module Τύποι
  class CatType < Types::BaseObject
   υλοποιεί Types::AnimalInterface

   πεδίο :hair_type, String, null: false
  end
end

module Τύποι
  class DogType < Types::BaseObject
    υλοποιεί Types::AnimalInterface

     πεδίο :breed, String, null: false
  end
end

Αυτό είναι! Έτοιμοι! Μια τελευταία ερώτηση: πώς μπορούμε να χρησιμοποιήσουμε αυτό που κάναμε από την πλευρά του πελάτη;

Δημιουργία του ερωτήματος

{
 allZoos : {
   zoo: {
      name
      city
      ζώα: {
        __typename

        ... on ElephantType {
          name
          age
          trunkLength
        }

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

Μπορούμε να χρησιμοποιήσουμε ένα πρόσθετο πεδίο __typename εδώ, το οποίο θα επιστρέψει τον ακριβή τύπο ενός συγκεκριμένου στοιχείου (π.χ. CatType). Πώς θα μοιάζει ένα δείγμα απάντησης;

{
  "allZoos": [

   {
      "name": "Natura Artis Magistra",
      "city": "Άμστερνταμ",
      "animals": [
        {
          "__typename": "ElephantType"
          "name": "Franco",
          "age": 28,
          "trunkLength": 9.27
         },
         {
         "__typename": "DogType"
         "name": "Jack",
         "age": 9,
         "breed": "Jack Russell Terrier"
        },
      ]
    }
  ]
} 

Ανάλυση

Ένα μειονέκτημα αυτής της προσέγγισης είναι προφανές. Στο ερώτημα, πρέπει να εισάγουμε το όνομα και την ηλικία σε κάθε τύπο, παρόλο που γνωρίζουμε ότι όλα τα ζώα έχουν αυτά τα πεδία. Αυτό δεν είναι ενοχλητικό όταν η συλλογή περιέχει εντελώς διαφορετικά αντικείμενα. Σε αυτή την περίπτωση, όμως, τα ζώα μοιράζονται σχεδόν όλα τα πεδία. Μπορεί να βελτιωθεί με κάποιο τρόπο;

Φυσικά! Κάνουμε την πρώτη αλλαγή στο αρχείο app/graphql/types/zoo_type.rb:

ενότητα Τύποι
  class ZooType < Types::BaseObject
    field :name, String, null: false
    field :city, String, null: false
    field :animals, [Types::AnimalInterface], null: false
  end
end

Δεν χρειαζόμαστε πλέον την ένωση που έχουμε ορίσει πριν. Αλλάζουμε Τύποι::AnimalType στο Τύποι::AnimalInterface.

Το επόμενο βήμα είναι να προσθέσουμε μια συνάρτηση που επιστρέφει έναν τύπο από το Τύποι :: AnimalInterface και προσθέστε επίσης μια λίστα με τύπους orphan_types, δηλαδή τύπους που δεν χρησιμοποιούνται ποτέ άμεσα:

ενότητα Τύποι
  module AnimalInterface
    include Types::BaseInterface

   πεδίο :name, String, null: false
   πεδίο :age, Ακέραιος αριθμός, 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

Χάρη σε αυτή την απλή διαδικασία, το ερώτημα έχει μια λιγότερο περίπλοκη μορφή:

{
  allZoos : {
   zoo: {
      name
      city
      ζώα: {
        __typename
        name
        age

       ... on ElephantType {
          trunkLength

       }
       ... on CatType {
          hairType

       }
       ... on DogType {
          breed

        }
      }
    }
  }
}

Περίληψη

GraphQL είναι μια πραγματικά εξαιρετική λύση. Αν δεν το ξέρετε ακόμα, δοκιμάστε το. Πιστέψτε με, αξίζει τον κόπο. Κάνει εξαιρετική δουλειά στην επίλυση προβλημάτων που εμφανίζονται, για παράδειγμα, στα REST APIs. Όπως έδειξα παραπάνω, πολυμορφισμός δεν αποτελεί πραγματικό εμπόδιο για αυτό. Παρουσίασα δύο μεθόδους για την αντιμετώπισή του.
Υπενθύμιση:

  • Εάν εργάζεστε σε έναν κατάλογο αντικειμένων με κοινή βάση ή κοινή διεπαφή - χρησιμοποιήστε τις διεπαφές,
  • Αν χειρίζεστε μια λίστα αντικειμένων με διαφορετική δομή, χρησιμοποιήστε μια διαφορετική διεπαφή - χρησιμοποιήστε την ένωση

Διαβάστε περισσότερα

GraphQL Ruby. Τι γίνεται με τις επιδόσεις;

Σιδηρόδρομοι και άλλα μέσα μεταφοράς

Ανάπτυξη Rails με TMUX, Vim, Fzf + Ripgrep

Σχετικά άρθρα

Ανάπτυξη λογισμικού

Κατασκευάστε μελλοντικά ασφαλείς εφαρμογές Web: γνώσεις από την ομάδα εμπειρογνωμόνων του The Codest

Ανακαλύψτε πώς η The Codest υπερέχει στη δημιουργία κλιμακούμενων, διαδραστικών εφαρμογών ιστού με τεχνολογίες αιχμής, παρέχοντας απρόσκοπτη εμπειρία χρήστη σε όλες τις πλατφόρμες. Μάθετε πώς η τεχνογνωσία μας οδηγεί στον ψηφιακό μετασχηματισμό και την επιχειρηματική...

THECODEST
Ανάπτυξη λογισμικού

Top 10 εταιρείες ανάπτυξης λογισμικού με έδρα τη Λετονία

Μάθετε για τις κορυφαίες εταιρείες ανάπτυξης λογισμικού της Λετονίας και τις καινοτόμες λύσεις τους στο τελευταίο μας άρθρο. Ανακαλύψτε πώς αυτοί οι τεχνολογικοί ηγέτες μπορούν να βοηθήσουν στην ανύψωση της επιχείρησής σας.

thecodest
Λύσεις Enterprise & Scaleups

Βασικά στοιχεία ανάπτυξης λογισμικού Java: Α Guide to Outsourcing Successfully (Οδηγός για την επιτυχή εξωτερική ανάθεση)

Εξερευνήστε αυτόν τον βασικό οδηγό για την επιτυχή ανάπτυξη λογισμικού outsourcing Java για να αυξήσετε την αποδοτικότητα, να αποκτήσετε πρόσβαση στην τεχνογνωσία και να οδηγήσετε την επιτυχία των έργων με The Codest.

thecodest
Ανάπτυξη λογισμικού

Ο απόλυτος οδηγός για το Outsourcing στην Πολωνία

Η έξαρση της outsourcing στην Πολωνία οφείλεται στις οικονομικές, εκπαιδευτικές και τεχνολογικές εξελίξεις, που ευνοούν την ανάπτυξη της πληροφορικής και το φιλικό προς τις επιχειρήσεις κλίμα.

TheCodest
Λύσεις Enterprise & Scaleups

Ο πλήρης οδηγός εργαλείων και τεχνικών ελέγχου πληροφορικής

Οι έλεγχοι ΤΠ διασφαλίζουν ασφαλή, αποτελεσματικά και συμβατά συστήματα. Μάθετε περισσότερα για τη σημασία τους διαβάζοντας ολόκληρο το άρθρο.

The Codest
Jakub Jakubowicz CTO & Συνιδρυτής

Εγγραφείτε στη βάση γνώσεών μας και μείνετε ενήμεροι για την τεχνογνωσία από τον τομέα της πληροφορικής.

    Σχετικά με εμάς

    The Codest - Διεθνής εταιρεία ανάπτυξης λογισμικού με κέντρα τεχνολογίας στην Πολωνία.

    Ηνωμένο Βασίλειο - Έδρα

    • Γραφείο 303B, 182-184 High Street North E6 2JA
      Λονδίνο, Αγγλία

    Πολωνία - Τοπικοί κόμβοι τεχνολογίας

    • Πάρκο γραφείων Fabryczna, Aleja
      Pokoju 18, 31-564 Κρακοβία
    • Πρεσβεία του εγκεφάλου, Konstruktorska
      11, 02-673 Βαρσοβία, Πολωνία

      The Codest

    • Αρχική σελίδα
    • Σχετικά με εμάς
    • Υπηρεσίες
    • Case Studies
    • Μάθετε πώς
    • Καριέρα
    • Λεξικό

      Υπηρεσίες

    • Συμβουλευτική
    • Ανάπτυξη λογισμικού
    • Backend Ανάπτυξη
    • Ανάπτυξη Frontend
    • Staff Augmentation
    • Backend Developers
    • Μηχανικοί cloud
    • Μηχανικοί δεδομένων
    • Άλλα
    • Μηχανικοί QA

      Πόροι

    • Γεγονότα και μύθοι σχετικά με τη συνεργασία με εξωτερικό συνεργάτη ανάπτυξης λογισμικού
    • Από τις ΗΠΑ στην Ευρώπη: Γιατί οι αμερικανικές νεοσύστατες επιχειρήσεις αποφασίζουν να μετεγκατασταθούν στην Ευρώπη
    • Σύγκριση υπεράκτιων κόμβων ανάπτυξης τεχνολογίας: Ευρώπη (Πολωνία), ASEAN (Φιλιππίνες), Ευρασία (Τουρκία)
    • Ποιες είναι οι κορυφαίες προκλήσεις των CTOs και των CIOs;
    • The Codest
    • The Codest
    • The Codest
    • Privacy policy
    • Website terms of use

    Πνευματικά δικαιώματα © 2025 από The Codest. Όλα τα δικαιώματα διατηρούνται.

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