製品の品質を落とさずに開発チームを拡大する方法
開発チームの規模を拡大中ですか?製品の品質を犠牲にすることなく成長する方法を学びましょう。このガイドでは、スケールする時期、チーム構成、採用、リーダーシップ、ツールなどの兆候に加え、The Codestがどのように...
この記事では、GraphQLにおけるポリモーフィズムの使い方を紹介する。しかしその前に、ポリモーフィズムとGraphQLが何であるかを思い出しておく価値がある。
ポリモーフィズム の重要な構成要素である。 オブジェクト指向プログラミング.物事を単純化するために、これは異なるクラスのオブジェクトが同じインターフェースにアクセスできるという事実に基づいている。つまり ルビー 開発者 が得られる。 多型 の3つである:
継承 は、親クラスと子クラス(つまり親クラスを継承するクラス)を作成することにあります。子クラスは親クラスの機能を受け継ぎ、また機能を変更したり追加したりすることができます。
例
クラス ドキュメント
  attr_reader :名前
終了
クラス PDFDocument < ドキュメント
  def 拡張
    :pdf
  終了
終了
class ODTDocument < ドキュメント
  def 拡張
    :odt
  終了
終了
モジュール ルビー には多くの使い方がある。そのひとつがミックスインだ(ミックスインについては 究極のブレークダウンルビー対Python).Rubyのミキシンは、他のプログラミング言語のインターフェイスと同じように使うことができます(例えば ジャワを含むオブジェクトに共通するメソッドを定義することができます。モジュールには読み取り専用のメソッドを含めるのがよい習慣です。つまり、このオブジェクトの状態を変更しないメソッドです。
例
課税モジュール
  デフタックス
     価格 * 0.23
  終了
終了
クラス Car
  課税対象を含む
 attr_reader :価格
終了
クラス Book
  課税対象を含む
 attr_reader :価格
終了
これは動的型付け言語の重要な特徴のひとつである。この名前は、「アヒルのように見え、アヒルのように泳ぎ、アヒルのように鳴くなら、それはおそらくアヒルである」という有名なテストに由来する。これは プログラマー は、与えられたオブジェクトがどのクラスに属しているかに関心を持つ必要はない。重要なのは、このオブジェクトに対して呼び出せるメソッドである。
上記の例で定義したクラスを使用する:
クラス 車
  attr_reader :価格
 def initialize(price)
    価格 = 価格
   終了
終了
クラス Book
  attr_reader :価格
 def initialize(price)
    価格 = 価格
  終了
終了
car = Car.new(20.0)
book = Book.new(10.0)
[車, 本].map(&:価格)
GraphQL はAPI用の比較的新しいクエリー言語である。その利点は、非常にシンプルな構文を持っていること、さらに、各顧客が望むものを正確に得ることができ、それ以外は何も得ることができないため、クライアントが正確に得たいものを決めることができることである。
のサンプルクエリ GraphQL:
{
  すべてのユーザー
     ユーザー
        id
        ログイン
        電子メール
       }
     }
   }
回答例
{
  "allUsers":{
    "users":[
     {
        "id":1,
        "login":"user1"、
        "email":"[email protected]"
      },
      {
        "id":2,
        "login":"user2"、
        "email":"[email protected]"
      },
    ]
  }
現時点で知るべきことはこれだけだろう。では、本題に入ろう。
問題とその解決策を最もよく理解するために、例を作ってみよう。その例が独創的で、かつかなり現実的なものであればいい。私たち一人ひとりがいつか遭遇する可能性のあるものだ。動物はどうだろう?そうだ!いいアイデアだ!

で書かれたバックエンドアプリケーションがあるとする。 Ruby on Rails.これは、上記のスキームを処理するためにすでに適応されている。また、すでに GraphQL を構成した。クライアントが以下の構造で問い合わせを行えるようにしたい:
{
 allZoos : {
    動物園{
      名前
      都市
      動物: {
        ...
      }
    }
  }
}
足りない情報を得るためには、3つの点の代わりに何を入れればいいのか。
以下、目標を達成するために必要なステップを紹介しよう。
まず、allZoosというクエリが何を意味するのかを定義する必要がある。そのためには、ファイルapp/graphql/types/query_type.rb とクエリーを定義する:
   モジュール Types
      class QueryType < Types::BaseObject
       フィールド :all_zoos, [Types::ZooType], null: false
       def all_zoos
          Zoo.all
       終了
    終了
 終了
クエリーはすでに定義されている。次は戻り値の型を定義する番だ。
最初に必要なタイプはZooTypeです。ファイルで定義しましょう。 app/graphql/types/ zoo_type.rb:
モジュール Types
  class ZooType < Types::BaseObject
    field :name, String, null: false
    field :city, String, null: false
    field :animals, [Types::AnimalType], null: false
  終了
終了
次にAnimalType型を定義する:
モジュール Types
  class AnimalType < Types::BaseUnion
   指定可能な型 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
私たちは何を見るのだろうか? コード 上記?
タイプ::ベースユニオン.self.resolve_object(obj, ctx)、これは、与えられたオブジェクトの型を返さなければならない。次のステップは、動物の種類を定義することである。しかし、いくつかのフィールドはすべての動物に共通であることがわかっている。それらをAnimalInterface型に含めよう:
モジュール Types
  モジュール AnimalInterface
    include Types::BaseInterface
    field :name, String, null: false
    field :age, 整数, null: false
  終了
終了
このインターフェイスがあれば、特定の動物のタイプを定義することができる:
モジュール Types
  class ElephantType < Types::BaseObject
    Types::AnimalInterface を実装
    フィールド :trunk_length, Float, null: false
  終了
終了
モジュール Types
  class CatType < Types::BaseObject
   Types::AnimalInterface を実装しています。
   フィールド :hair_type, String, null: false
  終了
終了
モジュール Types
  class DogType < Types::BaseObject
    Types::AnimalInterface を実装
     フィールド :breed, String, null: false
  終了
終了
そうだ!準備完了!最後の質問:クライアント側で行ったことをどのように使えばいいのでしょうか?
{
 allZoos : {
   動物園{
      名前
      都市
      動物: {
        名前
        ... on ElephantType { {...
          名前
          年齢
          体幹の長さ
        }
         ... on CatType { ...
          名前
          年齢
          ヘアタイプ
         }
         ... on DogType {
          名前
          年齢
          犬種
         }
       }
ここで追加の__typenameフィールドを使えば、与えられた要素の正確な型を返すことができる(例:CatType)。回答例はどのようになるでしょうか?
{
  "allZoos":[
   {
      "name":"Natura Artis Magistra"、
      "city":"アムステルダム"、
      "animals":[
        {
          "__typename":"エレファントタイプ"
          "name":"フランコ"、
          "age":28,
          「幹の長さ9.27
         },
         {
         "__typename":"DogType"
         "name":"Jack"、
         "age":9,
         犬種「ジャック・ラッセル・テリア
        },
      ]
    }
  ]
} 
この方法の欠点は明らかである。クエリーでは、すべての動物がこれらのフィールドを持っていることがわかっているにもかかわらず、それぞれのタイプに名前と年齢を入力しなければならない。これは、コレクションにまったく異なるオブジェクトが含まれている場合には気にならない。しかし、この場合、動物はほとんどすべてのフィールドを共有している。どうにか改善できないだろうか?
もちろんだ!ファイルに最初の変更を加える app/graphql/types/zoo_type.rb:
モジュール Types
  class ZooType < Types::BaseObject
    field :name, String, null: false
    field :city, String, null: false
    field :animals, [Types::AnimalInterface], null: false
  終了
終了
私たちはもはや、これまで定義してきた組合を必要としない。次のように変更する。 タイプ::アニマルタイプ への Types::AnimalInterface.
次のステップは、以下の型を返す関数を追加することである。 タイプ ::動物インターフェース さらに、直接使われることのない型であるorphan_typesのリストも追加した:
モジュール Types
  モジュール AnimalInterface
    include Types::BaseInterface
   field :name, String, null: false
   field :age, 整数, null: false
   definition_methods do
      def resolve_type(obj, ctx)
        if obj.is_a?(Elephant)
          象型
        elsif obj.is_a?(Cat)
          CatType
        elsif obj.is_a?(Dog)
          DogType
        end
      end
    end
    orphan_types Types::ElephantType, Types::CatType, Types::DogType
  end
終了
このシンプルな手順のおかげで、クエリーはそれほど複雑な形をしていない:
{
  allZoos : {
   動物園{
      名前
      都市
      動物: {
        名前
        名前
        年齢
       ... on ElephantType { {...
          幹の長さ
       }
       ... on CatType { 毛の長さ } ... on CatType { 毛の長さ
          毛の長さ
       }
       ... on DogType { 犬種
          犬種
        }
      }
    }
  }
}
GraphQL は本当に素晴らしいソリューションだ。まだ知らない人は試してみて。信じてほしい。これは、例えばREST APIに現れる問題を解決する上で素晴らしい仕事をしてくれる。上で示したように、 多型 は、そのための本当の障害ではない。私はそれに取り組むための2つの方法を提示した。
リマインダー
続きを読む