Using Inputs and Enums

enumeration type をそろそろ導入したほうがいいでしょう。PhotoCategory という名前の型を我々は導入していきます。それから input type も導入します。我々は PostPhotoInput という名前で導入することにします。

It’s time to introduce an enumeration type, PhotoCategory, and an input type, PostPhotoInput, to our typeDefs:

enum と input type を導入する
enum PhotoCategory {
  SELFIE
  PORTRAIT
  ACTION
  LANDSCAPE
  GRAPHIC
}

type Photo {
    #    ...
  category: PhotoCategory!
}

input PostPhotoInput {
  name: String!
  category: PhotoCategory = PORTRAIT
  description: String
}

type Mutation {
  postPhoto(input: PostPhotoInput!): Photo!
}

Chapter 4 において、これらの type は作成しましたね。PhotoShare アプリケーションのための schema を設計する際におこないました。今回もこのときと同じく、PhotoCategory という enumeration type を追加し、さらに photos にも category field を追加します。photo が resolving した際に、photo category がある状態になっていないといけません。つまり enumeration で定義した文字列のどれかにマッチした値を category フィールドが持つ必要があります。そのためには、user が新しい photo を post した際にも、category を取得する必要があります。

In Chapter 4, we created these types when we designed the schema for the PhotoShare application. We also added the PhotoCategory enumeration type and added a category field to our photos. When resolving photos, we need to make sure that the photo category — a string that matches the values defined in the enumeration type — is available. We also need to collect a category when users post new photos.

PostPhotoInput type を追加することで、postPhoto mutation への引数を単一のオブジェクトとして構造化しました。この input type はcategory というフィールドを持っています。ユーザーのポスト時にこの値がない場合にそなえて、PORTRAIT という値を default 値として設定しています。

We’ve added a PostPhotoInput type to organize the argument for the postPhoto mutation under a single object. This input type has a category field. Even when a user does not supply a category field as an argument, the default, PORTRAIT, will be used.

postPhoto resolver にも少し変更が必要です。photo, name, description, category の詳細情報は、今や input field の中にあります。ですので arg ではなく、代わりに arg.input にアクセスして値を取得するように変更します。

Mutation の変更
postPhoto(parent, args) {
  var newPhoto = {
    id: _id++,
    ...args.input
  };
  photos.push(newPhoto);
  return newPhoto;
}

For the postPhoto resolver, we need to make some adjustments, as well. The details for the photo, the name, description, and category are now nested within the input field. We need to make sure that we access these values at args.input instead of args:

では設定が終わったので、mutation を実行してみましょう。その際に新たな input type をクエリに追加します。

Now, we run the mutation with the new input type:

Mutation のクエリ
mutation newPhoto($input: PostPhotoInput!) {
  postPhoto(input: $input) {
    id
    name
    url
    description
    category
  }
}

Query Valiables パネルで、以下の JSON を送ります。

We also need to send the corresponding JSON in the Query Variables panel:

クエリの変数に以下を追加
{ 
  "input": {
    "name": "sample photo A", 
    "description": "A sample photo for our dataset" 
  } 
}

category が提供されていなければ、デフォルト値の PORTRAIT が使われます。category があれば、この値を enumeration type でヴァリデーションします。ヴァリデーションは、サーバーに送るオペレイションの前に行われます。有効な category の値であった場合には、resolver の argument に渡ります。

If the category is not supplied, it will default to PORTRAIT. Alternatively, if a value is provided for category, it will be validated against our enumeration type before the operation is even sent to the server. If it’s a valid category, it will be passed to the resolver as an argument.

input type を使うことによって、mutation へ渡す argument を reusable にでき、かつこの領域においてエラーを起こしづらくすることができます。とくに input type と enum を併用することで、さらに input の特定のフィールドにどの値がくるのかを明示することができ、堅牢になります。input と enum を組み合わせることで、有用性が非常に向上します。

With input types, we can make passing arguments to mutations more reusable and less error-prone. When combining input types and enums, we can be more specific about the types of inputs that can be supplied to specific fields. Inputs and enums are incredibly valuable and are made even better when you use them together.