GraphQLでDateTimeを扱う時、フォーマットを指定する。
GraphQLにはScalarTypeというクラスが存在する。
ScalarTypeは配列やオブジェクト(いわゆるkey-valueペア)、enum等ではないタイプの基底クラスになる。
GraphQLではこのScalarTypeをベースとした5つの基本タイプが仕様として定義されている。
- Int - 符号付き32ビット整数
- Float - 倍精度少数
- String - UTF-8文字シーケンス
- Boolean - true or false
- ID - GUID
これだけだとDateTime等で困るので、DateTimeのGraphQLTypeを作ってみる。
date_time_type.rb
graphql-rubyを使う
https://github.com/rmosolgo/graphql-ruby
DateTimeType = GraphQL::ScalarType.define do name 'DateTimeType' description 'ActiveRecord::Type::DateTimeに対応したType' end
このままだとクエリに対する出力結果が
{ "data": { "series": { "created_at": "2017-01-09T18:55:30.000Z" } } }
になる。せっかくGraphQLなので、フォーマットもクエリとして与えられるようにしたい。
created_atフィールドをいじる
普通にcreated_atを一属性として扱うだけなら
field :title, DateTimeType
の記述だけで済むが、今回は引数formatを与えると、その通りに整形してくれるようにする。
field :created_at do type DateTimeType argument :format, types.String resolve ->(obj, args, ctx) { return obj.created_at if args[:format].nil? obj.created_at.strftime(args[:format]) } end
これでqueryを叩く
{ series(id: 3) { created_at(format:"%Y年%m月%d日 %H:%M:%S") } }
↓
{ "data": { "series": { "created_at": "2017年01月09日 18:55:30" } } }
良い。 本当はフォーマットの仕組みをTypeそのものに持たせたいのだけれど、TypeのresultがStringを取ることになるので適切では無さそう。