GraphQLのライブラリをなぜか書いている話 GraphQLは良いぞ!

RailsのモデルをフロントのJavaScriptで持っているデータとリアルタイム同期させるためのgem(ar_sync)を作っている。
そのために、俺の考えた最強のシリアライザ(ar_serializer)を作っていたら、ほぼGraphQL互換(mutationはないけど)ぽい作りになった。
せっかくなのでGraphQLのパーサを書いて、GraphiQLが動くところまでできた。 GraphQLは良いぞ
f:id:tompng:20180828231056p:plain

ar_serializerについて

https://github.com/tompng/ar_serializer
queryは、as_jsonとかincludesの引数みたいな(見慣れたものに近い)記法で書く
GraphQLのqueryと機能的にはだいたい同じ
モデルにガリガリfield書いてく 個人的には書きやすいと思う(typeも指定しなければ適当にassociationとかから引っ張ってくる)
N+1回避しつつqueryで柔軟にjson作る、のが目的で作っているので、graphql-batch内臓みたいなもの
aliasの内部表現がgraphqlと逆(response_key:field_name field_name: {as: response_key} ちょっとここは直したい)
権限管理用にnamespaceってものをつけた ArSerializer.serialize model, query, use: current_user.namespace_for_role
GraphQLのparserは気合いで書いたので、対応してない記法も多分ある(graphql-rubyも文字列escape周り似たようなものだけど)

雑感

GraphQL、すごくよくできてる。最高!

少なくともqueryの部分は。
理想のものを作ろうとした結果、もうすでにあるものにたどり着いて、自分は何をやっていたんだろうという気分にさせられた。

graphql-ruby 大変そう

ActiveRecord(かActiveModel)で使うの前提だとしてgraphql-rubyは記述がちょっとだるそう
graphql-batch 微妙じゃない?(graphql-rubyが提供すべき機能がないせいで無理してない?)

Query Language 別にJSONで良くなかった?

argumentsの書式がjsonじゃないので、文字列で埋め込めない
{post(${JSON.stringify(param)}){name}} などができない。代わりに、 {post($param){name}} とvariablesを使えばいいけど
それならもともと独自言語じゃなくてJSONだったらよかったんじゃないかなぁ、param埋め込みも自由だしvariablesなんて要らなかったのでは
確かに読みやすい言語だけど、そのparserを各言語用にみんなそれぞれ作らなきゃいけないし...

mutationはメリットが良くわからない

accepts_nested_attributes_forでできることを別に解決してないように見える
postに対して、commentを10件つける、ということがGraphQL使えばうまくいく、わけでも無さそう
RESTで、返り値(@post)に対するgraphqlのqueryを指定できれば良くない?
(取得系はGraphQL 更新系はREST+返り値のquery がいいんじゃないかな、特にRailsだと)

Relay connectionsもちょっと引っかかるところがある

ページネーション実現するならこうなるだろうな、とは思うけど
複数のpostsに対して、commentsを(after指定で)取れてもあまり意味無さそうで、
特に使わない方向に自由度が高くなっているような(別にいいんだけど、なんかもやっとする)

{
  allPosts {
    comments(first: 5, after: "id15") {
      edges{
        cursor
        node{ id text }
      }
    }
  }
}

REST apiでpagination実現+データの形式はGraphQLのqueryで指定、でも良いような気がする

どうしよう

ar_syncを、ar_serializer捨ててgraphql-ruby依存で作るべきかどうか悩み中(答えはnoな気がする)
とはいえ、mutationもrelayもまだ使ってないから使ったら感想変わるかもしれない