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

GraphQL Highway

58b40ae3b0db6cf0202a3802e9dd70fe?s=47 cockscomb
December 17, 2021

GraphQL Highway

銀座Rails#40

58b40ae3b0db6cf0202a3802e9dd70fe?s=128

cockscomb

December 17, 2021
Tweet

Transcript

  1. ۜ࠲3BJMT (SBQI2-ͷߴ଎ಓ࿏

  2. (SBQI2-ͱ͸

  3. (SBQI2-͸'BDFCPPLʹΑͬͯ࡞ΒΕͨ w ೥'BDFCPPLʹΑͬͯ։ൃ։࢝ w χϡʔεϑΟʔυͷ಺༰Λදݱ͢ΔͨΊʹߟҊ w ೥(SBQI2-ൃදʢ3FMBZ΋ಉ೥ʹൃදʣ w ೥ςΫχΧϧϓϨϏϡʔΛ୤͢Δ w

    (JU)VC͕(SBQI2-"1*Λఏڙ։࢝ w ೥(SBQI2-'PVOEBUJPOʹҠ؅͞Εͨ
  4. (SBQI2-͸8FC"1*ͷͨΊͷΫΤϦݴޠ औಘ͞ΕΔσʔλ͕ΫΤϦͱҰக͢Δ query { posts { title } } {

    "posts": [ { "title": "Hello World" }, { "title": "Hi" } ] }
  5. ΫΤϦݴޠ͕ඞཁͳཧ༝ (SBQI2-͕3&45ʹରͯ࣋ͭ͠Ξυόϯςʔδ w ΦʔόʔϑΣονϯάΛ๷͛Δ w ϦΫΤετ਺ΛݮΒͤΔ w ΫϥΠΞϯτͷมԽʹରͯ͠ॊೈ

  6. (SBQI2-Ͱ͸ΦʔόʔϑΣονϯάΛ๷͛Δ ඞཁҎ্ͷσʔλΛऔಘͯ͠͠·͏͜ͱΛΦʔόʔϑΣονϯάͱ͍͏ { "posts": [ { "title": "Hello World", "body":

    "Lorem ipsum", "authorId": "1" }, { "title": "Hi", "body": "Hi there.", "authorId": "2" } ] } { "posts": [ { "title": "Hello World" }, { "title": "Hi" } ] }
  7. (SBQI2-Ͱ͸ΦʔόʔϑΣονϯάΛ๷͛Δ w ΫϥΠΞϯτ͕ඞཁͳσʔλΛཁٻ͢ΔͨΊΦʔόʔϑΣονϯά͕ى͖ͳ͍ w ΦʔόʔϑΣονϯά͕๷͕ΕΔ͜ͱͰ w సૹྔΛখ͘͞Ͱ͖Δ w αʔόʔαΠυ΋ϦιʔεΛઅ໿Ͱ͖Δ w

    ΞϯμʔϑΣονϯά͸όά😢
  8. (SBQI2-Ͱ͸ϦΫΤετ਺ΛݮΒͤΔ ґଘؔ܎ͷ͋ΔϦιʔεΛҰ౓ͰऔಘͰ͖Δ GET /posts GET /author/1 GET /author/2 query {

    posts { title author { name } } }
  9. (SBQI2-Ͱ͸ϦΫΤετ਺ΛݮΒͤΔ w ͻͱͭͷը໘ʹඞཁͳσʔλΛϦΫΤετͰऔಘͰ͖Δͷ͕ཧ૝ w ϦΫΤετʹ͔͔Δ͕࣌ؒ355 3PVOE5SJQ5JNF  w ฒྻʹϦΫΤετͰ͖Ε͹ෳ਺ͷϦΫΤετ͕͋ͬͯ΋355ͰࡁΉ͕ w

    ϦΫΤετؒʹґଘؔ܎͕͋Δͱ/355ʹͳΔ w 3&45Ͱ͸࣮ݱ͕ࠔ೉ w ৔߹ʹΑͬͯ͸3&45෩ͷԿ͔ʹͳ͍ͬͯ͘😢
  10. (SBQI2-͸ΫϥΠΞϯτͷมԽʹॊೈ "1*ʹྺ࢙తܦҢ͕஝ੵ͍ͯ͘͜͠ͱΛ๷͛Δ { "title": "Hello World", "body": "Lorem ipsum", "tags":

    ["essay", "blog"], // ࠓ͸࢖͍ͬͯͳ͍͕ޓ׵ੑͷͨΊʹ࢒͢ "tag_objects": [ { "name": "essay", "id": "1" }, { "name": "blog", "id": "2" } ] }
  11. (SBQI2-͸ΫϥΠΞϯτͷมԽʹॊೈ w ͻͱͭͷը໘ʹඞཁͳσʔλΛϦΫΤετͰऔಘͰ͖Δͷ͕ཧ૝ͱ͢Δͱ w ը໘ͷදࣔཁૉΛม͑Δ౓ʹ"1*Λม͑Δͷ͸ͭΒ͍ w ͢Ͱʹ࢖͍ͬͯͳ͍ϑΟʔϧυΛޓ׵ੑͷͨΊʹ࢒ͨ͠Γ͢Δ w 8FCϑϩϯτΤϯυ͚ͩͩͱ؇࿨͞ΕΔ w

    ωΠςΟϒΞϓϦ͸ݹ͍όʔδϣϯ͕࢒Γଓ͚Δ৔߹͕ଟ͍
  12. (SBQI2-ͱ͸ 8FC"1*ͷͨΊͷΫΤϦݴޠ w ݱ୅తͳΫϥΠΞϯταΠυͷ։ൃʹదԠ͍ͯ͠Δ w 3&45తͳΞϓϩʔνͰ͸ղܾ͠ʹ͍͘՝୊Λղܾ͢Δ w ΦʔόʔϑΣονϯάΛ๷͛Δ w ϦΫΤετ਺ΛݮΒͤΔ

    w ΫϥΠΞϯτͷมԽʹରͯ͠ॊೈ w ͍͔ʹ΋Αͦ͞͏Ͱ͢Ͷʂ
  13. (SBQI2-ͷجຊ

  14. (SBQI2-ͷͭͷΦϖϨʔγϣϯ w 2VFSZ w Ϧιʔεͷऔಘɻ(&5ʹ૬౰ w .VUBUJPO w Ϧιʔεͷมߋɻ1045165%&-&5&ʹ૬౰ w

    4VCTDSJQUJPO w Ϧιʔεͷߪಡɻ8FC4PDLFUͳͲΛ࢖͏ɻࠓճ͸ׂѪ
  15. ΦϖϨʔγϣϯͷॻࣜ লུͰ͖Δ෦෼΋͋Δ query { post(id: "1") { title } }

    
 query GetPost { post(id: "1") { title } } 
 query GetPost($id: ID!) { post(id: $id) { title } }
  16. ΦϖϨʔγϣϯͷॻࣜ w RVFSZNVUBUJPOTVCTDSJQUJPO w ΦϖϨʔγϣϯ໊ w ม਺ w ϑΟʔϧυͷબ୒ w

    ύϥϝʔλΛऔΕΔ query GetPost($id: ID!) { post(id: $id) { title } }
  17. (SBQI2-ͷεΩʔϚ 4%- 4DIFNB%F fi OJUJPO-BOHVBHF type Query { # ...

    } type Mutation { # ... } schema { query: Query mutation: Mutation }
  18. (SBQI2-ͷܕ w εΧϥܕ w /PO/VMMܕ w Ϧετܕ w ྻڍܕ 


    w ΦϒδΣΫτܕ w Πϯϓοτܕ w ϢχΦϯܕ w ΠϯλʔϑΣʔε
  19. εΧϥܕ w *OUŠූ߸෇͖Ϗοτ੔਺ w 'MPBUŠഒਫ਼౓ුಈখ਺఺਺ w 4USJOHŠ65'จࣈྻɻೋॏҾ༻ූͰғ͏ w #PPMFBOŠਅِ஋ɻUSVFGBMTF w

    *%ŠϢχʔΫͳࣝผࢠɻ࣮ଶ͸จࣈྻ w ಠࣗʹఆٛ͢Δ͜ͱ΋͋Δ
  20. /PO/VMMܕ w (SBQI2-ͷܕ͸σϑΥϧτͰOVMM஋Λڐ༰͢Δ w OVMM஋͕ೖΒͳ͍͜ͱΛ໌֬ʹ͢Δͷ͕/PO/VMMܕ w Λޙஔ͢Δͱ/PO/VMMܕʹͳΔ String # null஋Λڐ༰͢Δ

    String! # null஋Λڐ༰͠ͳ͍
  21. Ϧετܕ w εΫΤΞϒϥέοτͰғ͏ w /PO/VMMܕͱͷ૊Έ߹Θͤʹ஫ҙ [Post] [Post]! [Post!] [Post!]!

  22. ྻڍܕ enum Order { ASC DESC } type Query {

    posts(order: Order = DESC): [Post!]! }
  23. ΦϒδΣΫτܕ type Author { name: String! } type Post {

    title: String! author: Author! } type Query { posts: [Post!]! }
  24. Πϯϓοτܕ w ύϥϝʔλʹΦϒδΣΫτܕ͸࢖͑ͳ͍ input CreatePostInput { title: String! body: String!

    } type Mutation { createPost(input: CreatePostInput!): Post! }
  25. ϢχΦϯܕ type Comment { text: String! } type Trackback {

    title: String! url: String! } union Feedback = Comment | Trackback type Post { title: String! feedbacks: [Feedback!]! }
  26. ΠϯλʔϑΣʔε interface Publication { title: String! body: String! } type

    Page implements Publication { title: String! body: String! } type Post implements Publication { title: String! body: String! comments: [Comment!]! }
  27. σΟϨΫςΟϒ w εΩʔϚ΍ΦϖϨʔγϣϯʹϝλσʔλΛ͚ͭΒΕΔ directive @deprecated( reason: String = "No longer

    supported” ) on FIELD_DEFINITION | ENUM_VALUE type Query { posts: [Post!]! @deprecated }
  28. (SBQI2-ͷجຊ w 2VFSZ.VUBUJPO4VCTDSJQUJPO͕͋Δ w ܕ͕͋Δ w εΩʔϚ͕ॻ͚Δ w ࢓༷͕ఆΊΒΕ͍ͯΔ w

    IUUQTTQFDHSBQIRMPSH0DUPCFS
  29. Τϥʔ͸ϨεϙϯεͷFSSPSTͰฦ͢ ΤϥʔͷϑΥʔϚοτ͸࢓༷ͰఆΊΒΕ͍ͯΔ { "data": null, "errors": [ { "message": "body

    could not be fetched", "locations": [ { "line": 4, "column": 4 } ], "path": ["post", "body"] } ] }
  30. (SBQI2-PWFS)551 HJUIVCDPNHSBQIRMHSBQIRMPWFSIUUQ w (SBQI2-"1*Λ)551Ͱఏڙ͢Δඪ४తͳ࢓༷͕ࡦఆத w ୯ҰͷΤϯυϙΠϯτʢయܕతʹ͸/graphqlʣͰ"1*Λఏڙ w GET΋͘͠͸POST { "query":

    "", "operationName": "", "variables": {} }
  31. (SBQI2-ͷઃܭ

  32. εΩʔϚઃܭ w ΞϓϦέʔγϣϯͷυϝΠϯʹ߹Θͤͨઃܭ͕ඞཁ w 3&45Ͱ͸Ϧιʔεʹରͯ͠$36%ૢ࡞Λఆٛ͢Δͷ͕جຊ w (SBQI2-Ͱ΋ͦΕ͸ಉ͚ͩ͡Ͳɺ೉͘͠ײ͡Δͱࢥ͏ w ࢓༷ͱͯ͠ఆٛ͞Ε͍ͯΔ΋ͷͰ͸ͳ͍͕ఆੴ͕͋Δ w

    ఆੴʹै͏ͱΫϥΠΞϯτʹͱͬͯ౎߹͕͍͍
  33. Ϧιʔεͷൃݟ w Ϧιʔεͷൃݟ͕ελʔτ஍఺ w 3&45ͱಉ͡ w Ϧιʔε͸ΦϒδΣΫτܕͰදݱ w αʔόʔͷ಺෦࣮૷ͱ෼͚ͯߟ͑Δ w

    υϝΠϯϞσϧʹै͏ type Blog { id: ID! name: String! } type Post { id: ID! title: String! body: String! }
  34. άϥϑߏ଄Λ࡞Δ ؔ࿈͢ΔϦιʔεΛϑΟʔϧυͰḷΕΔΑ͏ʹ͢Δ type Author { id: ID! name: String! }

    type Post { id: ID! title: String! authorId: ID! } type Author { id: ID! name: String! } type Post { id: ID! title: String! author: Author! }
  35. άϥϑߏ଄Λ࡞Δ ؔ࿈͢ΔϦιʔεΛϑΟʔϧυͰḷΕΔΑ͏ʹ͢Δ type Query { posts( blogId: ID!, page: Int!

    ): [Post!]! } type Blog { posts(page: Int!): [Post!]! } type Query { blog(id: ID!): Blog! }
  36. (SBQI2-ͷػೳΛ׆͔͢ w ྻڍܕ͕࢖͑Δͱ͜ΖͰ͸ੵۃతʹ࢖͏ w ΠϯλʔϑΣʔε΍ϢχΦϯܕ͕͏·͘࢖͑Δͱ͜Ζ͕͋Ε͹࢖͏ w /PO/VMMܕʹ͢΂͖ͱ͜ΖΛܾΊΔ

  37. ΠϯλʔϑΣʔεΛ࢖ͬͨઃܭ 6($αΠτͰϢʔβʔΛෳ਺ͷܕͰදݱͨ͠ࣄྫ w ΞΫηε͖͍ͯͯ͠Δਓ͸7JTJUPSܕ w ౤ߘऀ͸6TFSܕ w ͲͪΒ΋"VUIPSΠϯλʔϑΣʔεΛ࣮૷ w 8PSLܕͷBVUIPSϑΟʔϧυ͸"VUIPSΛฦ͢

    w ࣗ෼ͷ࡞඼ͳΒ7JTJUPSܕʹͳ͍ͬͯΔ
  38. /PO/VMMܕΛͲΕ͘Β͍࢖͏΂͖͔ ;ͨͭͷελϯε͕͋Δ w ՄೳͳݶΓ/PO/VMMܕΛ࢖͏ w υϝΠϯϞσϧʹ߹Θͤͯ/PO/VMMܕΛͪΌΜͱ࢖͏ w OVMMΛڐ͢ͷ͸υϝΠϯϞσϧ্OVMM͕ҙຯΛ࣋ͭ৔߹͚ͩ w ཁॴཁॴͰOVMMΛڐ༰͢Δ

    w ෼ࢄγεςϜͷҰ෦͕ো֐Λى͍ͯ͜͠Δͱ͖ʹඋ͑Δ w શମΛΤϥʔʹ͢ΔΑΓҰ෦ΛOVMMʹͯ͠ฦ͢
  39. 7JFXFS (SBQI2-ʹΞΫηε͖ͯͨ͠ར༻ऀΛࢦ͢γϣʔτΧοτ w ༻ҙ͓ͯ͘͠ͱศར w ΫϥΠΞϯτϥΠϒϥϦʹΑͬͯ͸ w Query.viewerΛಛผѻ͍͢Δ type Viewer

    { name: String! } type Query { viewer: Viewer }
  40. /PEFΠϯλʔϑΣʔε ࠶औಘՄೳͳϦιʔε w JEͰࣝผՄೳͰ͋Δ͜ͱΛظ଴ w άϩʔόϧʹҰҙ w *Eͷ஋ͰΫΤϦͰ͖Δ w ΫϥΠΞϯτϥΠϒϥϦʹΑͬͯ͸

    w JEΛ࢖ͬͯΩϟογϡΛਖ਼نԽ͢Δ interface Node { id: ID! } type Query { node(id: ID!): Node }
  41. ࠶औಘ͕ͳͥॏཁͳͷ͔ ҰཡͱύʔϚϦϯΫ w ҰཡͰ͸λΠτϧ͚ͩΛදࣔ w ύʔϚϦϯΫͰ͸ຊจ΋දࣔ w JE͕͋Ε͹࠶औಘͰ͖Δ query GetPostList

    { posts { id title } } query GetPost($id: ID!) { post(id: $id) { id title body } }
  42. ࠶औಘ͕ͳͥॏཁͳͷ͔ ϖʔδωʔγϣϯ w ϖʔδ໨Ҏ߱Λऔಘ͢Δͱ͖ type Blog { id: ID! posts(page:

    Int!): [Post!]! } query { blog(id: "1") { id posts(page: 1) { id } } }
  43. /PEFΠϯλʔϑΣʔε ࠶औಘՄೳͳϦιʔεΛҰൠԽͨ͠΋ͷ w 3FMBZ༝དྷ w ύʔϚϦϯΫΛ࣋ͭΑ͏ͳϦιʔε w JEͷ஋͸యܕతʹ͸ w CBTF

    ܕ໊ϓϥΠϚϦΩʔ  w αʔόʔͰ͸ܕ໊ͰॲཧΛ෼͚Δ w ΫϥΠΞϯτ͸PQBRVFʹѻ͏ interface Node { id: ID! } type Post implements Node { id: ID! }
  44. $POOFDUJPO ϖʔδωʔγϣϯͷந৅Խ w 3FMBZ༝དྷ w ΧʔιϧΛ࢖ͬͨϖʔδωʔγϣϯ w ΫϥΠΞϯτϥΠϒϥϦʹΑͬͯ͸ w ࣗಈతʹϖʔδωʔγϣϯͰ͖Δ

    type PageInfo { hasNextPage: Boolean! hasPreviousPage: Boolean! startCursor: String endCursor: String } type PostEdge { cursor: String! node: Post! } type PostConnection { pageInfo: PageInfo! edges: [PostEdge!]! } type Blog { posts(first: Int!, after: String): PostConnection! }
  45. ϖʔδωʔγϣϯ w جຊ͸Χʔιϧϕʔεͷϖʔδωʔγϣϯ w ϖʔδωʔγϣϯ͢ΔϑΟʔϧυΛ࣋ͭΦϒδΣΫτ͕࠶औಘՄೳ͔͕ॏཁ w 2VFSZɺ7JFXFSɺ/PEF w ͳΜͰ΋ϖʔδωʔγϣϯ͠ͳ͍͍ͯ͘ w

    ཁૉ͕ݸఔ౓ʹऩ·Δͱܾ·͍ͬͯͨΒϦετܕΛબͿ
  46. 3FMBZͷ(SBQI2-4FSWFS4QFDJGJDBUJPO $POWFOUJPOPWFS$PO fi HVSBUJPO w 3FMBZ͸'BDFCPPL੡ͷ(SBQI2-ΫϥΠΞϯτϥΠϒϥϦ w αʔόʔʹ௥Ճͷ࢓༷Λཁٻ͢Δ w ΦϒδΣΫτͷ࠶औಘŠ/PEF

    w ϖʔδωʔγϣϯŠ$POOFDUJPO w 3FMBZΛ࢖Θͳ͍ͳΒै͏ඞཁ͸ͳ͍͕ɺ฿͓͍ͬͯͯଛ͸ͳ͍ w ͍ͣΕ΋Ұൠతͳ՝୊ͳͷͰ
  47. .VUBUJPO͸Ϧιʔεͷ$6%͔Β͸͡ΊΔ w DSFBUF3FTPVSDF w VQEBUF3FTPVSDF w EFMFUF3FTPVSDF w ҙຯ͝ͱʹ෼ׂͯ͠΋͍͍ w

    େ͖͘ͳΓ͗͢ͳ͍Α͏ʹ type Mutation { createPost( input: PostInput!): Post! updatePost( id: ID!, input: PostInput!): Post! deletePost(id: ID!): ID! createDraftPost( input: PostInput!): Post! publishPost(id: ID!): Post! }
  48. .VUBUJPOͷύϥϝʔλͱ໭Γ஋ w ύϥϝʔλ͸ΠϯϓοτܕΛ࢖͏ w ࣅͨߏ଄ʹͳΔͳΒڞ༗͢Δ w ฦΓ஋͸/PEF͔*%Λ࢖͏ w DSFBUFͱVQEBUFͰ͸/PEFΛฦ͢ w

    EFMFUFͰ͸*%Λฦ͢ input PostInput { title: String! body: String! } type Mutation { createPost( input: PostInput!): Post! updatePost( id: ID!, input: PostInput!): Post! deletePost(id: ID!): ID! }
  49. (SBQI2-ͷεΩʔϚઃܭ w ઌਓͷ஌ܙʹֶͿ w ఆੴʹै͏ w (JU)VCͷ(SBQI2-"1*ͳͲΛࢀߟʹ͢Δ w IUUQTHJUIVCDPN4IPQJGZHSBQIRMEFTJHOUVUPSJBM w

    ࠷ऴతʹ͸໨తΛୡ੒Ͱ͖Δ͔͕Ұ൪ॏཁ w ΫϥΠΞϯτʹͱͬͯ౎߹ͷ͍͍"1*͕͍͍"1*
  50. $PEFGJSTU͔4DIFNBGJSTU͔

  51. ίʔυϑΝʔετͱεΩʔϚϑΝʔετ (SBQI2-εΩʔϚͷ4PVSDFPG5SVUI͕Ͳ͔͜ w (SBQI2-"1*Λ࡞Δͱ͖ʹ࠷ॳʹ൑அ͢Δ͜ͱ w ϥΠϒϥϦʹΑͬͯҧ͏ w ίʔυʹΑͬͯεΩʔϚ͕ܾ·ΔͳΒίʔυϑΝʔετ w HSBQIRMSVCZ͸جຊతʹ͸ͬͪ͜

    w εΩʔϚΛ࡞ͬͯͦΕʹ߹ΘͤͯίʔυΛॻ͘ͳΒεΩʔϚϑΝʔετ
  52. ίʔυϑΝʔετͷ͍͍ͱ͜Ζ w ίʔυͱεΩʔϚͷରԠ͕औΓ΍͍͢ w ϓϩάϥϛϯάݴޠͷػೳΛ׆͔͠΍͍͢ w ίʔυͷ࠶ར༻ w ϞδϡʔϧԽ

  53. εΩʔϚϑΝʔετͷ͍͍ͱ͜Ζ w εΩʔϚத৺ʹͳΔ w εΩʔϚʹ͍ͭͯٞ࿦͠΍͍͢ w ҙਤͤͣඇޓ׵ͳมߋΛߦ͏ͷΛ๷͛Δ

  54. ίʔυϑΝʔετ͔εΩʔϚϑΝʔετ͔ ݁ہͲͪΒ͕͍͍ͷ͔ w εΩʔϚϑΝʔετͷํ͕ࣗવͳϑϩʔͰ͸͋Δ w εΩʔϚϑΝʔετ͕ྲྀߦ͕ͬͨίʔυϑΝʔετ΁ͷ༳Γ໭͕͋͠Δ w ͓͢͢Ί͸ w εΩʔϚ͔Βίʔυੜ੒͢ΔʢHRMHFOͳͲʣ

    w ίʔυ͔ΒεΩʔϚΛੜ੒ͯ͠ίϛοτ͢Δ w ͍ͣΕʹͯ͠΋εΩʔϚʹ͍ͭͯαʔόʔɾΫϥΠΞϯτؒͷٞ࿦͕ॏཁ
  55. ίʔυϑΝʔετͰεΩʔϚΛग़ྗ͢Δ w εΩʔϚΛμϯϓ͢Δ w εΩʔϚ͸ϦϙδτϦʹೖΕΔ w εΩʔϚͷมߋ͸ϨϏϡʔ͢Δ w ࠷৽ͷεΩʔϚ͕ग़ྗ͞Ε͍ͯΔ͔͸ςετͰ୲อ w

    IUUQTHSBQIRMSVCZPSHUFTUJOHTDIFNB@TUSVDUVSFIUNM # lib/tasks/graphql.rake task dump_schema: :environment do schema_defn = GraphqlRubyExerciseSchema.to_definition schema_path = "app/graphql/schema.graphql" File.write(Rails.root.join(schema_path), schema_defn) puts "Updated #{ schema_path}" end
  56. (SBQI2-"1*Λ࣮૷͢Δ

  57. (SBQI2-"1*ͷ࣮૷ w HSBQIRMSVCZΛ࢖͏ w ϥΠϒϥϦͷυΩϡϝϯτʹै͏

  58. ͻͱ·ͣΦϒδΣΫτܕΛ࡞Δ w ΦϒδΣΫτͱϑΟʔϧυ͕ॏཁ w %#্ͷߏ଄ʹ߹ΘͤΔඞཁ͸ͳ͍ w HSBQIRMSVCZͰ͸ $ rails g

    graphql:object Model w "DUJWF3FDPSEͷϞσϧͷ৘ใ͕ࣗಈతʹ࢖ΘΕΔ w ϛεϦʔσΟϯάͰ͸͋Δ module Types class UserType < Types :: BaseObject field :name, String, null: false end end
  59. جຊతʹ͸ϦκϧόΛॻ͚͹͍͍ Ϧκϧό˺ίϯτϩʔϥ w ϑΟʔϧυΛղܾ͢Δͷ͕Ϧκϧό w (SBQI2-ʹಛ༗ͷॲཧΛॻ͘ w HSBQIRMSVCZͰ͸ w ϑΟʔϧυͱಉ໊ͷϝιου

    module Types class QueryType < Types :: BaseObject include GraphQL :: Types :: Relay : : HasNodeField include GraphQL :: Types :: Relay : : HasNodesField field :all_blogs, BlogType.connection_type def all_blogs Blog.all.order(id: :desc) end end end
  60. Ϧκϧό͸ωετ͢Δ w ϦκϧόͰಘΒΕͨΦϒδΣΫτ͕ 
 ·ͨϦκϧόΛ࣋ͭ w 2VFSZˠ#MPHˠ1PTU w ศར w

    / ໰୊ͷԹচʜʜ module Types class BlogType < Types :: BaseObject implements GraphQL :: Types : : Relay :: Node global_id_field :id field :owner, UserType, null: false def owner object.owner end field :name, String, null: false field :posts, PostType.connection_type do end def posts object.posts.order(datetime: :desc) end end end
  61. ϦκϧόΛॻ͘ͱ͖ͷࢦ਑ w ΫΤϦͷϦκϧό͸ݺͼग़͞ΕΔॱং͕ෆఆͰ͋ΔલఏΛஔ͘ w ϥΠϒϥϦʹΑͬͯ͸ฒྻʹ࣮ߦ͞ΕΔՄೳੑ͕͋Δ w ෭࡞༻͕ͳ͍Α͏ʹ w ϛϡʔςʔγϣϯ͸ॻ͍ͨॱʹ࣮ߦ͞ΕΔͷͰؾʹ͠ͳ͍ w

    ϦκϧόʹϏδωεϩδοΫΛॻ͔ͳ͍ w ϏδωεϩδοΫ͸Ϟσϧʹॻ͘
  62. ΠϯλʔϑΣʔε΍ϢχΦϯΛฦ͢ͱ͖͸஫ҙ ΦϒδΣΫτͱܕͷରԠΛࣔ͢ඞཁ͕͋Δ w ΠϯλʔϑΣʔεͱͯ͠ฦ͢ͱ͖ 
 ࣮ࡍʹ͸Ͳͷܕ͔ϥΠϒϥϦʹ఻͑Δ w HSBQIRMSVCZͰ͸ w Schema.resolve_type

    def self.resolve_type(abstract_type, obj, ctx) case obj when User Types :: UserType when Blog Types :: BlogType when Post Types :: PostType else raise(GraphQL :: RequiredImplementationMissingError) end end
  63. 3FMBZʹରԠͤ͞Δ HSBQIRMSVCZ͕͍͍ͩͨ΍ͬͯ͘ΕΔ $ rails generate \ graphql:install - - relay

    w (MPCBM*%Λར༻ͨ͠/PEFͷ࣮૷ def self.id_from_object(object, type_definition, query_ctx) object_id = object.to_global_id.to_s object_id = object_id.sub("gid: //#{ GlobalID.app}/", "") encoded_id = Base64.urlsafe_encode64(object_id) encoded_id = encoded_id.sub( /= +/, "") type_hint = type_definition.graphql_name.first " #{ type_hint}_ # { encoded_id}" end def self.object_from_id(encoded_id_with_hint, query_ctx) _type_hint, encoded_id = encoded_id_with_hint.split("_", 2) id = Base64.urlsafe_decode64(encoded_id) full_global_id = "gid: //#{ GlobalID.app}/ #{ id}" GlobalID :: Locator.locate(full_global_id) end
  64. 3FMBZʹରԠͤ͞Δ /PEFΠϯλʔϑΣʔε • GraphQL :: Types :: Relay : :

    Node w HMPCBM@JE@ fi FMEΛࢦఆ module Types class UserType < Types :: BaseObject implements GraphQL :: Types :: Relay :: Node global_id_field :id field :name, String, null: false end end
  65. 3FMBZʹରԠͤ͞Δ $POOFDUJPO w connection_type w ಺෦తʹP ff TFUϕʔεʹͳ͍ͬͯΔ module Types

    class QueryType < Types :: BaseObject field :all_blogs, BlogType.connection_type def all_blogs Blog.all.order(id: :desc) end end end
  66. ίϯςΩετΛ࢖͏ ϦΫΤετʹඥ͍ͮͨσʔλ͸ίϯςΩετʹ֨ೲ͢Δ w ϩάΠϯϢʔβʔͳͲ w ΫΤϦΛ࣮ߦ͢ΔίϯτϩʔϥʔͰ 
 ίϯςΩετΛ࡞Δ def execute

    variables = prepare_variables(params[:variables]) query = params[:query] operation_name = params[:operationName] context = { # Query context goes here, for example: # current_user: current_user, } result = GraphqlRubyExerciseSchema.execute( query, variables: variables, context: context, operation_name: operation_name ) render json: result rescue StandardError = > e raise e unless Rails.env.development? handle_error_in_development(e) end
  67. (SBQIJ2-Λ࢖͏ (SBQI2-*%& $ rails generate graphql:install w HSBQIRMSVCZͰ͸ w /graphiqlʹࣗಈͰηοτΞοϓ͞ΕΔ

    w 3BJMT͕"1*Ϟʔυͷ৔߹͸ηοτΞοϓ͞Εͳ͍ w ผʹ༻ҙ͢Δͱศར
  68. (SBQI2-"1*࣮૷্ͷཹҙ఺

  69. / ໰୊ w BVUIPSͷϦκϧόΛφΠʔϒʹ࣮૷ w 1PTUͷ਺͚ͩ4&-&$5 SELECT * FROM author

    WHERE id = ?; type Author { id: ID! name: String! } type Post { id: ID! title: String! author: Author! } type Query { allPosts(first: Int!, after: String): PostConnection! }
  70. / ໰୊ରࡦ σʔλϩʔμʔΛ࢖͏ w ಡΈࠐΈΛ஗Ԇͤ͞Δ࢓૊Έ SELECT * FROM author WHERE

    id IN (?, ?, ?); w HSBQIRMSVCZͰ͸ w GraphQL :: DataloaderΛ࢖͏ class Sources : : ActiveRecordObject < GraphQL : : Dataloader :: Source def initialize(model_class) @model_class = model_class end def fetch(ids) records = @model_class.where(id: ids) ids.map { |id| records.find { |r| r.id = = id.to_i } } end end field :author, UserType, null: false def author dataloader .with(Sources :: ActiveRecordObject, :: User) .load(object.author_id) end
  71. %P4߈ܸ w ෳࡶͳΫΤϦͰ%P4߈ܸͰ͖Δ w ಛʹ࠶ؼతͳεΩʔϚͰ͸༰қ w #MPHˠ1PTUˠ#MPHˠ1PTUˠʜ query { blog(id:

    "1") { posts(first: 100) { edges { node { blog { posts(first: 100) { edges { node { . . . } } } } } } } } }
  72. %P4߈ܸରࡦ ΫΤϦ౰ͨΓͷॲཧྔΛ੍໿͢Δ w λΠϜΞ΢τͤ͞Δʢuse GraphQL : : Schema : :

    Timeout, max_seconds: 2ʣ w ΫΤϦͷ"45ͷ࣌఺Ͱ੍໿ w ਂ੍͞ݶʢmax_depth 10ʣ w ෳࡶ͞Ͱ੍ݶʢmax_complexity 100ʣ w Ϩʔτ੍ݶ w (JU)VC͸࣌ؒ౰ͨΓͷෳࡶ͞ͷείΞͰ੍ݶ͍ͯ͠Δ
  73. ඇެ։"1*ͳΒ ΫϥΠΞϯτͷ։ൃऀ͕ΠϯαΠμʔʹݶΒΕΔͳΒ w ϓϩμΫγϣϯͰ͸*OTUSPTQFDUJPOΛ௵͢ w 1FSTJTUFE2VFSZΛ࢖͏

  74. ϓϩμΫγϣϯͰ͸*OUSPTQFDUJPOΛ௵͢ εΩʔϚ৘ใΛ஌ΒΕʹ͘͘͢Δ w *OUSPTQFDUJPO͸(SBQI2-ͷεΩʔϚ৘ใΛऔಘ͢ΔಛผͳΫΤϦ w ࢓༷ͰఆΊΒΕ͍ͯΔ w ֎෦͔ΒεΩʔϚ৘ใ͕ಘΒΕΔʢ(SBQIJ2-ͳͲͰ׆༻͞ΕΔʣ w ϓϩμΫγϣϯ؀ڥͰ͸*OUSPTQFDUJPOͰ͖ͳ͓ͯ͘͘͠

    • disable_introspection_entry_points if Rails.env.production? w εΩʔϚ৘ใ͕ਪଌͰ͖ͳ͘ͳΔΘ͚Ͱ͸ͳ͍͜ͱʹ஫ҙ
  75. 1FSTJTUFE2VFSZΛ࢖͏ ҙਤ͠ͳ͍ΫΤϦΛड͚෇͚ͳ͍ w ΫϥΠΞϯτ͕ૹ৴͢ΔΫΤϦΛϋογϡ஋ͱ૊Ͱαʔόʔʹొ࿥͓ͯ͘͠ w ΫϥΠΞϯτ͔Β͸࣮ࡍͷΫΤϦͷ୅ΘΓʹϋογϡ஋ΛૹΔ w ΫΤϦͷ಺༰Λ஌ΒΕͣʹࡁΉ w ࣄલʹొ࿥͞Ε͍ͯͳ͍ΫΤϦΛ๷͛Δ

    • GraphQL :: Pro : : OperationStore w ΫϥΠΞϯτϥΠϒϥϦͷ΄ͱΜͲ͕ରԠ͍ͯ͠Δ
  76. ΦϒβʔόϏϦςΟͷ௿Լ w (SBQI2-͸୯ҰͷΤϯυϙΠϯτΛ࢖͏ w POST /graphql w 3&45͸Ϧιʔε΍ॲཧ͝ͱʹΤϯυϙΠϯτ͕෼͔Ε͍ͯͨ w (SBQI2-ͷ৔߹͸ΞΫηεϩάͰ͸৘ใ͕଍Γͳ͍

    w ฏۉͷϨΠςϯγ΍Τϥʔ཰Λݟͯ΋Կ͕ى͖͍ͯΔ͔Θ͔Βͳ͍
  77. ΦϒβʔόϏϦςΟΛ֬อ͢Δ w τϨʔγϯά͢Δ w Ϧκϧόͷݺͼग़͠΍*0Λه࿥ • GraphQL :: Tracing

  78. ஗͗͢Δ(SBQI2-"1*ࣄ݅ w 1ZUIPOͰ(SBQI2-"1*Λ࡞͍͕ͬͯͨ૝ఆΑΓ஗͍෦෼͕͋ͬͨ w ϓϩϑΝΠϦϯά͍ͯ͘͠ͱɺ$16͕ϘτϧωοΫ w +40/ʹγϦΞϥΠζ͢Δͱ͜Ζ͕஗͔ͬͨ w ཁૉ͕ଟ͔ͬͨΓωετ͕ਂ͔ͬͨΓ͢ΔͱϑΟʔϧυ਺͕ଟ͘ͳΔ w

    +*5ίϯύΠϧͰ͖ͨΒ଎͘ͳΓͦ͏ʁ
  79. ·ͱΊ

  80. (SBQI2- w ཁٻ͞ΕΔ஌ࣝͷྔ͕ଟΊ w ϦονͳΫϥΠΞϯτ޲͚ͷ8FC"1*ʹ͸ͦΕ͚ͩͷ͜ͱ͕ඞཁ w 8FC"1*ʹඞཁͳϓϥΫςΟε͕͢΂ͯ٧·͍ͬͯΔ w ͭ·Γʜ w

    (SBQI2-͸Ϩʔϧ w HSBQIRMSVCZ͸Α͘Ͱ͖͍ͯΔ