Upgrade to Pro — share decks privately, control downloads, hide ads and more …

カスタムしながら理解するGraphQL Connection

yana-gi
October 25, 2024

カスタムしながら理解するGraphQL Connection

Kaigi on Rails 2024 (2024.10.25)

yana-gi

October 25, 2024
Tweet

More Decks by yana-gi

Other Decks in Programming

Transcript

  1. 2 ⾃⼰紹介 minne事業部 プロダクト開発チーム 2022年 中途⼊社 yana-gi やなぎ • 2021年

    フィヨルドブートキャンプ卒業 • 2022年〜 GMOペパボ株式会社 Webアプリケーションエンジニア • GitHub : yana-gi • X : @yana_gis • ビールとお茶とみはしのあんみつが好き
  2. 3

  3. 4 • webの主な技術スタック ◦ Ruby on Rails ◦ Next.js ◦

    MySQL • 段階的に移⾏中 ◦ フロント画⾯をRailsからNext.jsへ ◦ APIをREST APIからGraphQL APIへ • GraphQL APIの実装はgraphql-ruby minne
  4. 9 1. GraphQLとは 1.1. minneでのGraphQL API使⽤例 1.2. minneで新規検索エンジンを導⼊する 1.3. Connection

    Type 2. Custom Connection 2.1. クエリをしてからデータを返すまで 2.2. Custom Connectionの実装 2.3. 遅延評価 アジェンダ
  5. GraphQLとは 13 エンドポイントで取得するデータを指定する • GET /api/products.json • GET /api/categories.json •

    GET /api/cart.json • GET /api/viewer.json 1ページを表⽰するのに4回APIを実⾏する必要がある REST APIの場合
  6. • データの開始位置を指定する • offset と limit で取得する ◦ offset :

    何件⽬から取得するか ◦ limit : 何件取得するか SQLの場合 オフセットページネーション 22 SELECT * FROM products LIMIT 10 OFFSET 30;
  7. • Connection: ノード(データ)を リスト形式で取得する • Edge: ノード間の関係性や付加情報 • Node: 実際のデータ本体

    Connection のノードの取得クエリ 26 query { products(first: 10) { # ProductConnection Type edges { # ProductEdge Type cursor node { # Product Type name id }, …
  8. 29 Connection Typeの実装 field :items, Types::ItemType.connection_type, null: false def products

    object.products # ActiveRecord Relationの場合 end fieldのTypeをconnection_typeに指定する サポートされているクラスの場合、要素を全て渡す
  9. • 検索エンジンはREST APIで提供されている ◦ ページネーションはoffsetページネーションのみ • 結果を取得したデータを扱うクラスは ActiveRecordではない ◦ Connection

    Typeでサポートされていないクラスになりそう ◦ サポートされていない場合は?🤔 改めて今回やりたいこと 30
  10. Custom Connectionを実装する Custom Connection Typeの実装 32 https://graphql-ruby.org/pagination/using_connections.html#return-collections def products #

    ActiveRecordのリレーションを取得 relation = object.items # 作成したCustom Connection Typeのインスタンスを返す Connections::ProductsConnection.new(relation) end 参考: https://graphql-ruby.org/pagination/using_connections.html#return-collections
  11. GraphQL::Pagination::Connection を継承したConnection Typeを作る 実装する必要があるメソッドが4つある Custom Connectionの実装 33 参考: https://graphql-ruby.org/pagination/custom_connections.html class

    Connections::ProductsConnection < GraphQL::Pagination::Connection def nodes; ...; end # 返すべきノードの配列を取得 def has_next_page; ...; end # 次のページが存在するかを判定 def has_previous_page; ...; end # 前のページが存在するかを判定 def cursor_for(item); ...; end # 指定されたノードのカーソルを⽣成 end
  12. 1. 疑問に思ったことの答え • Connection の offset (開始位置)はどうやって決まる? → Connection Class

    でcursorから計算している 2. resolverを通った後にConnection Class で offset が決まる わかったこと💡 41
  13. 1. GraphQLでページングを⾏うにはConnectionを使う 2. 独⾃のモデルでConnectionを使うにはCustom Connectionを定義する 3. Connection Type Classでoffsetが決まる 4.

    offsetを利⽤するためにresolverではPromiseクラスを利 ⽤して遅延評価を⾏う まとめ & 実装してみて分かったこと 51
  14. • チームメンバー ◦ kazu(@kazuhitonakayam)さん ◦ saki(@Saki-htr)さん • 資料のレビュー ◦ daiki(@doew)さん

    ◦ pyamaさん • ⼤元のPromiseクラスやCustom Connection Typeの実装 ◦ ogidowさん special thanks 53