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

GraphQL Highway

cockscomb
December 17, 2021

GraphQL Highway

銀座Rails#40

cockscomb

December 17, 2021
Tweet

More Decks by cockscomb

Other Decks in Technology

Transcript

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

    View Slide

  2. (SBQI2-ͱ͸

    View Slide

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

    View Slide

  4. (SBQI2-͸8FC"1*ͷͨΊͷΫΤϦݴޠ
    औಘ͞ΕΔσʔλ͕ΫΤϦͱҰக͢Δ
    query {


    posts {


    title


    }


    }
    {


    "posts": [


    {


    "title": "Hello World"


    },


    {


    "title": "Hi"


    }


    ]


    }

    View Slide

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

    View Slide

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


    "posts": [


    {


    "title": "Hello World",


    "body": "Lorem ipsum",


    "authorId": "1"


    },


    {


    "title": "Hi",


    "body": "Hi there.",


    "authorId": "2"


    }


    ]


    }
    {


    "posts": [


    {


    "title": "Hello World"


    },


    {


    "title": "Hi"


    }


    ]


    }

    View Slide

  7. (SBQI2-Ͱ͸ΦʔόʔϑΣονϯάΛ๷͛Δ
    w ΫϥΠΞϯτ͕ඞཁͳσʔλΛཁٻ͢ΔͨΊΦʔόʔϑΣονϯά͕ى͖ͳ͍
    w ΦʔόʔϑΣονϯά͕๷͕ΕΔ͜ͱͰ
    w సૹྔΛখ͘͞Ͱ͖Δ
    w αʔόʔαΠυ΋ϦιʔεΛઅ໿Ͱ͖Δ
    w ΞϯμʔϑΣονϯά͸όά😢

    View Slide

  8. (SBQI2-Ͱ͸ϦΫΤετ਺ΛݮΒͤΔ
    ґଘؔ܎ͷ͋ΔϦιʔεΛҰ౓ͰऔಘͰ͖Δ
    GET /posts


    GET /author/1


    GET /author/2
    query {


    posts {


    title


    author {


    name


    }


    }


    }

    View Slide

  9. (SBQI2-Ͱ͸ϦΫΤετ਺ΛݮΒͤΔ
    w ͻͱͭͷը໘ʹඞཁͳσʔλΛϦΫΤετͰऔಘͰ͖Δͷ͕ཧ૝
    w ϦΫΤετʹ͔͔Δ͕࣌ؒ355 3PVOE5SJQ5JNF

    w ฒྻʹϦΫΤετͰ͖Ε͹ෳ਺ͷϦΫΤετ͕͋ͬͯ΋355ͰࡁΉ͕
    w ϦΫΤετؒʹґଘؔ܎͕͋Δͱ/355ʹͳΔ
    w 3&45Ͱ͸࣮ݱ͕ࠔ೉
    w ৔߹ʹΑͬͯ͸3&45෩ͷԿ͔ʹͳ͍ͬͯ͘😢

    View Slide

  10. (SBQI2-͸ΫϥΠΞϯτͷมԽʹॊೈ
    "1*ʹྺ࢙తܦҢ͕஝ੵ͍ͯ͘͜͠ͱΛ๷͛Δ
    {


    "title": "Hello World",


    "body": "Lorem ipsum",


    "tags": ["essay", "blog"],
    //
    ࠓ͸࢖͍ͬͯͳ͍͕ޓ׵ੑͷͨΊʹ࢒͢


    "tag_objects": [


    {


    "name": "essay",


    "id": "1"


    },


    {


    "name": "blog",


    "id": "2"


    }


    ]


    }

    View Slide

  11. (SBQI2-͸ΫϥΠΞϯτͷมԽʹॊೈ
    w ͻͱͭͷը໘ʹඞཁͳσʔλΛϦΫΤετͰऔಘͰ͖Δͷ͕ཧ૝ͱ͢Δͱ
    w ը໘ͷදࣔཁૉΛม͑Δ౓ʹ"1*Λม͑Δͷ͸ͭΒ͍
    w ͢Ͱʹ࢖͍ͬͯͳ͍ϑΟʔϧυΛޓ׵ੑͷͨΊʹ࢒ͨ͠Γ͢Δ
    w 8FCϑϩϯτΤϯυ͚ͩͩͱ؇࿨͞ΕΔ
    w ωΠςΟϒΞϓϦ͸ݹ͍όʔδϣϯ͕࢒Γଓ͚Δ৔߹͕ଟ͍

    View Slide

  12. (SBQI2-ͱ͸
    8FC"1*ͷͨΊͷΫΤϦݴޠ
    w ݱ୅తͳΫϥΠΞϯταΠυͷ։ൃʹదԠ͍ͯ͠Δ
    w 3&45తͳΞϓϩʔνͰ͸ղܾ͠ʹ͍͘՝୊Λղܾ͢Δ
    w ΦʔόʔϑΣονϯάΛ๷͛Δ
    w ϦΫΤετ਺ΛݮΒͤΔ
    w ΫϥΠΞϯτͷมԽʹରͯ͠ॊೈ
    w ͍͔ʹ΋Αͦ͞͏Ͱ͢Ͷʂ

    View Slide

  13. (SBQI2-ͷجຊ

    View Slide

  14. (SBQI2-ͷͭͷΦϖϨʔγϣϯ
    w 2VFSZ
    w Ϧιʔεͷऔಘɻ(&5ʹ૬౰
    w .VUBUJPO
    w Ϧιʔεͷมߋɻ1045165%&-&5&ʹ૬౰
    w 4VCTDSJQUJPO
    w Ϧιʔεͷߪಡɻ8FC4PDLFUͳͲΛ࢖͏ɻࠓճ͸ׂѪ

    View Slide

  15. ΦϖϨʔγϣϯͷॻࣜ
    লུͰ͖Δ෦෼΋͋Δ
    query {


    post(id: "1") {


    title


    }


    }

    query GetPost {


    post(id: "1") {


    title


    }


    }

    query GetPost($id: ID!) {


    post(id: $id) {


    title


    }


    }

    View Slide

  16. ΦϖϨʔγϣϯͷॻࣜ
    w RVFSZNVUBUJPOTVCTDSJQUJPO
    w ΦϖϨʔγϣϯ໊
    w ม਺
    w ϑΟʔϧυͷબ୒
    w ύϥϝʔλΛऔΕΔ
    query GetPost($id: ID!) {


    post(id: $id) {


    title


    }


    }

    View Slide

  17. (SBQI2-ͷεΩʔϚ
    4%- 4DIFNB%F
    fi
    OJUJPO-BOHVBHF

    type Query {


    #
    ...


    }


    type Mutation {


    #
    ...


    }


    schema {


    query: Query


    mutation: Mutation


    }

    View Slide

  18. (SBQI2-ͷܕ
    w εΧϥܕ
    w /PO/VMMܕ
    w Ϧετܕ
    w ྻڍܕ

    w ΦϒδΣΫτܕ
    w Πϯϓοτܕ
    w ϢχΦϯܕ
    w ΠϯλʔϑΣʔε

    View Slide

  19. εΧϥܕ
    w *OUŠූ߸෇͖Ϗοτ੔਺
    w 'MPBUŠഒਫ਼౓ුಈখ਺఺਺
    w 4USJOHŠ65'จࣈྻɻೋॏҾ༻ූͰғ͏
    w #PPMFBOŠਅِ஋ɻUSVFGBMTF
    w *%ŠϢχʔΫͳࣝผࢠɻ࣮ଶ͸จࣈྻ
    w ಠࣗʹఆٛ͢Δ͜ͱ΋͋Δ

    View Slide

  20. /PO/VMMܕ
    w (SBQI2-ͷܕ͸σϑΥϧτͰOVMM஋Λڐ༰͢Δ
    w OVMM஋͕ೖΒͳ͍͜ͱΛ໌֬ʹ͢Δͷ͕/PO/VMMܕ
    w Λޙஔ͢Δͱ/PO/VMMܕʹͳΔ
    String # null஋Λڐ༰͢Δ


    String! # null஋Λڐ༰͠ͳ͍


    View Slide

  21. Ϧετܕ
    w εΫΤΞϒϥέοτͰғ͏
    w /PO/VMMܕͱͷ૊Έ߹Θͤʹ஫ҙ
    [Post]


    [Post]!


    [Post!]


    [Post!]!

    View Slide

  22. ྻڍܕ
    enum Order {


    ASC


    DESC


    }


    type Query {


    posts(order: Order = DESC): [Post!]!


    }

    View Slide

  23. ΦϒδΣΫτܕ
    type Author {


    name: String!


    }


    type Post {


    title: String!


    author: Author!


    }


    type Query {


    posts: [Post!]!


    }

    View Slide

  24. Πϯϓοτܕ
    w ύϥϝʔλʹΦϒδΣΫτܕ͸࢖͑ͳ͍
    input CreatePostInput {


    title: String!


    body: String!


    }


    type Mutation {


    createPost(input: CreatePostInput!): Post!


    }

    View Slide

  25. ϢχΦϯܕ
    type Comment {


    text: String!


    }


    type Trackback {


    title: String!


    url: String!


    }


    union Feedback = Comment | Trackback


    type Post {


    title: String!


    feedbacks: [Feedback!]!


    }

    View Slide

  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!]!


    }

    View Slide

  27. σΟϨΫςΟϒ
    w εΩʔϚ΍ΦϖϨʔγϣϯʹϝλσʔλΛ͚ͭΒΕΔ
    directive @deprecated(


    reason: String = "No longer supported”


    ) on FIELD_DEFINITION | ENUM_VALUE


    type Query {


    posts: [Post!]! @deprecated


    }

    View Slide

  28. (SBQI2-ͷجຊ
    w 2VFSZ.VUBUJPO4VCTDSJQUJPO͕͋Δ
    w ܕ͕͋Δ
    w εΩʔϚ͕ॻ͚Δ
    w ࢓༷͕ఆΊΒΕ͍ͯΔ
    w IUUQTTQFDHSBQIRMPSH0DUPCFS

    View Slide

  29. Τϥʔ͸ϨεϙϯεͷFSSPSTͰฦ͢
    ΤϥʔͷϑΥʔϚοτ͸࢓༷ͰఆΊΒΕ͍ͯΔ
    {


    "data": null,


    "errors": [


    {


    "message": "body could not be fetched",


    "locations": [


    { "line": 4, "column": 4 }


    ],


    "path": ["post", "body"]


    }


    ]


    }

    View Slide

  30. (SBQI2-PWFS)551
    HJUIVCDPNHSBQIRMHSBQIRMPWFSIUUQ
    w (SBQI2-"1*Λ)551Ͱఏڙ͢Δඪ४తͳ࢓༷͕ࡦఆத
    w ୯ҰͷΤϯυϙΠϯτʢయܕతʹ͸/graphqlʣͰ"1*Λఏڙ
    w GET΋͘͠͸POST
    {


    "query": "",


    "operationName": "",


    "variables": {}


    }

    View Slide

  31. (SBQI2-ͷઃܭ

    View Slide

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

    View Slide

  33. Ϧιʔεͷൃݟ
    w Ϧιʔεͷൃݟ͕ελʔτ஍఺
    w 3&45ͱಉ͡
    w Ϧιʔε͸ΦϒδΣΫτܕͰදݱ
    w αʔόʔͷ಺෦࣮૷ͱ෼͚ͯߟ͑Δ
    w υϝΠϯϞσϧʹै͏
    type Blog {


    id: ID!


    name: String!


    }


    type Post {


    id: ID!


    title: String!


    body: String!


    }

    View Slide

  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!


    }

    View Slide

  35. άϥϑߏ଄Λ࡞Δ
    ؔ࿈͢ΔϦιʔεΛϑΟʔϧυͰḷΕΔΑ͏ʹ͢Δ
    type Query {


    posts(


    blogId: ID!,


    page: Int!


    ): [Post!]!


    }
    type Blog {


    posts(page: Int!): [Post!]!


    }


    type Query {


    blog(id: ID!): Blog!


    }

    View Slide

  36. (SBQI2-ͷػೳΛ׆͔͢
    w ྻڍܕ͕࢖͑Δͱ͜ΖͰ͸ੵۃతʹ࢖͏
    w ΠϯλʔϑΣʔε΍ϢχΦϯܕ͕͏·͘࢖͑Δͱ͜Ζ͕͋Ε͹࢖͏
    w /PO/VMMܕʹ͢΂͖ͱ͜ΖΛܾΊΔ

    View Slide

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

    View Slide

  38. /PO/VMMܕΛͲΕ͘Β͍࢖͏΂͖͔
    ;ͨͭͷελϯε͕͋Δ
    w ՄೳͳݶΓ/PO/VMMܕΛ࢖͏
    w υϝΠϯϞσϧʹ߹Θͤͯ/PO/VMMܕΛͪΌΜͱ࢖͏
    w OVMMΛڐ͢ͷ͸υϝΠϯϞσϧ্OVMM͕ҙຯΛ࣋ͭ৔߹͚ͩ
    w ཁॴཁॴͰOVMMΛڐ༰͢Δ
    w ෼ࢄγεςϜͷҰ෦͕ো֐Λى͍ͯ͜͠Δͱ͖ʹඋ͑Δ
    w શମΛΤϥʔʹ͢ΔΑΓҰ෦ΛOVMMʹͯ͠ฦ͢

    View Slide

  39. 7JFXFS
    (SBQI2-ʹΞΫηε͖ͯͨ͠ར༻ऀΛࢦ͢γϣʔτΧοτ
    w ༻ҙ͓ͯ͘͠ͱศར
    w ΫϥΠΞϯτϥΠϒϥϦʹΑͬͯ͸
    w Query.viewerΛಛผѻ͍͢Δ
    type Viewer {


    name: String!


    }


    type Query {


    viewer: Viewer


    }

    View Slide

  40. /PEFΠϯλʔϑΣʔε
    ࠶औಘՄೳͳϦιʔε
    w JEͰࣝผՄೳͰ͋Δ͜ͱΛظ଴
    w άϩʔόϧʹҰҙ
    w *Eͷ஋ͰΫΤϦͰ͖Δ
    w ΫϥΠΞϯτϥΠϒϥϦʹΑͬͯ͸
    w JEΛ࢖ͬͯΩϟογϡΛਖ਼نԽ͢Δ
    interface Node {


    id: ID!


    }


    type Query {


    node(id: ID!): Node


    }

    View Slide

  41. ࠶औಘ͕ͳͥॏཁͳͷ͔
    ҰཡͱύʔϚϦϯΫ
    w ҰཡͰ͸λΠτϧ͚ͩΛදࣔ
    w ύʔϚϦϯΫͰ͸ຊจ΋දࣔ
    w JE͕͋Ε͹࠶औಘͰ͖Δ
    query GetPostList {


    posts {


    id


    title


    }


    }


    query GetPost($id: ID!) {


    post(id: $id) {


    id


    title


    body


    }


    }

    View Slide

  42. ࠶औಘ͕ͳͥॏཁͳͷ͔
    ϖʔδωʔγϣϯ
    w ϖʔδ໨Ҏ߱Λऔಘ͢Δͱ͖ type Blog {


    id: ID!


    posts(page: Int!): [Post!]!


    }


    query {


    blog(id: "1") {


    id


    posts(page: 1) {


    id


    }


    }


    }

    View Slide

  43. /PEFΠϯλʔϑΣʔε
    ࠶औಘՄೳͳϦιʔεΛҰൠԽͨ͠΋ͷ
    w 3FMBZ༝དྷ
    w ύʔϚϦϯΫΛ࣋ͭΑ͏ͳϦιʔε
    w JEͷ஋͸యܕతʹ͸
    w CBTF ܕ໊ϓϥΠϚϦΩʔ

    w αʔόʔͰ͸ܕ໊ͰॲཧΛ෼͚Δ
    w ΫϥΠΞϯτ͸PQBRVFʹѻ͏
    interface Node {


    id: ID!


    }


    type Post implements Node {


    id: ID!


    }

    View Slide

  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!


    }

    View Slide

  45. ϖʔδωʔγϣϯ
    w جຊ͸Χʔιϧϕʔεͷϖʔδωʔγϣϯ
    w ϖʔδωʔγϣϯ͢ΔϑΟʔϧυΛ࣋ͭΦϒδΣΫτ͕࠶औಘՄೳ͔͕ॏཁ
    w 2VFSZɺ7JFXFSɺ/PEF
    w ͳΜͰ΋ϖʔδωʔγϣϯ͠ͳ͍͍ͯ͘
    w ཁૉ͕ݸఔ౓ʹऩ·Δͱܾ·͍ͬͯͨΒϦετܕΛબͿ

    View Slide

  46. 3FMBZͷ(SBQI2-4FSWFS4QFDJGJDBUJPO
    $POWFOUJPOPWFS$PO
    fi
    HVSBUJPO
    w 3FMBZ͸'BDFCPPL੡ͷ(SBQI2-ΫϥΠΞϯτϥΠϒϥϦ
    w αʔόʔʹ௥Ճͷ࢓༷Λཁٻ͢Δ
    w ΦϒδΣΫτͷ࠶औಘŠ/PEF
    w ϖʔδωʔγϣϯŠ$POOFDUJPO
    w 3FMBZΛ࢖Θͳ͍ͳΒै͏ඞཁ͸ͳ͍͕ɺ฿͓͍ͬͯͯଛ͸ͳ͍
    w ͍ͣΕ΋Ұൠతͳ՝୊ͳͷͰ

    View Slide

  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!


    }

    View Slide

  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!


    }

    View Slide

  49. (SBQI2-ͷεΩʔϚઃܭ
    w ઌਓͷ஌ܙʹֶͿ
    w ఆੴʹै͏
    w (JU)VCͷ(SBQI2-"1*ͳͲΛࢀߟʹ͢Δ
    w IUUQTHJUIVCDPN4IPQJGZHSBQIRMEFTJHOUVUPSJBM
    w ࠷ऴతʹ͸໨తΛୡ੒Ͱ͖Δ͔͕Ұ൪ॏཁ
    w ΫϥΠΞϯτʹͱͬͯ౎߹ͷ͍͍"1*͕͍͍"1*

    View Slide

  50. $PEFGJSTU͔4DIFNBGJSTU͔

    View Slide

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

    View Slide

  52. ίʔυϑΝʔετͷ͍͍ͱ͜Ζ
    w ίʔυͱεΩʔϚͷରԠ͕औΓ΍͍͢
    w ϓϩάϥϛϯάݴޠͷػೳΛ׆͔͠΍͍͢
    w ίʔυͷ࠶ར༻
    w ϞδϡʔϧԽ

    View Slide

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

    View Slide

  54. ίʔυϑΝʔετ͔εΩʔϚϑΝʔετ͔
    ݁ہͲͪΒ͕͍͍ͷ͔
    w εΩʔϚϑΝʔετͷํ͕ࣗવͳϑϩʔͰ͸͋Δ
    w εΩʔϚϑΝʔετ͕ྲྀߦ͕ͬͨίʔυϑΝʔετ΁ͷ༳Γ໭͕͋͠Δ
    w ͓͢͢Ί͸
    w εΩʔϚ͔Βίʔυੜ੒͢ΔʢHRMHFOͳͲʣ
    w ίʔυ͔ΒεΩʔϚΛੜ੒ͯ͠ίϛοτ͢Δ
    w ͍ͣΕʹͯ͠΋εΩʔϚʹ͍ͭͯαʔόʔɾΫϥΠΞϯτؒͷٞ࿦͕ॏཁ

    View Slide

  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

    View Slide

  56. (SBQI2-"1*Λ࣮૷͢Δ

    View Slide

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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  61. ϦκϧόΛॻ͘ͱ͖ͷࢦ਑
    w ΫΤϦͷϦκϧό͸ݺͼग़͞ΕΔॱং͕ෆఆͰ͋ΔલఏΛஔ͘
    w ϥΠϒϥϦʹΑͬͯ͸ฒྻʹ࣮ߦ͞ΕΔՄೳੑ͕͋Δ
    w ෭࡞༻͕ͳ͍Α͏ʹ
    w ϛϡʔςʔγϣϯ͸ॻ͍ͨॱʹ࣮ߦ͞ΕΔͷͰؾʹ͠ͳ͍
    w ϦκϧόʹϏδωεϩδοΫΛॻ͔ͳ͍
    w ϏδωεϩδοΫ͸Ϟσϧʹॻ͘

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  67. (SBQIJ2-Λ࢖͏
    (SBQI2-*%&
    $ rails generate graphql:install


    w HSBQIRMSVCZͰ͸
    w /graphiqlʹࣗಈͰηοτΞοϓ͞ΕΔ
    w 3BJMT͕"1*Ϟʔυͷ৔߹͸ηοτΞοϓ͞Εͳ͍
    w ผʹ༻ҙ͢Δͱศར

    View Slide

  68. (SBQI2-"1*࣮૷্ͷཹҙ఺

    View Slide

  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!


    }

    View Slide

  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

    View Slide

  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 {


    . .
    .


    }


    }


    }


    }


    }


    }


    }


    }


    }

    View Slide

  72. %P4߈ܸରࡦ
    ΫΤϦ౰ͨΓͷॲཧྔΛ੍໿͢Δ
    w λΠϜΞ΢τͤ͞Δʢuse GraphQL
    :
    :
    Schema
    : :
    Timeout, max_seconds: 2ʣ
    w ΫΤϦͷ"45ͷ࣌఺Ͱ੍໿
    w ਂ੍͞ݶʢmax_depth 10ʣ
    w ෳࡶ͞Ͱ੍ݶʢmax_complexity 100ʣ
    w Ϩʔτ੍ݶ
    w (JU)VC͸࣌ؒ౰ͨΓͷෳࡶ͞ͷείΞͰ੍ݶ͍ͯ͠Δ

    View Slide

  73. ඇެ։"1*ͳΒ
    ΫϥΠΞϯτͷ։ൃऀ͕ΠϯαΠμʔʹݶΒΕΔͳΒ
    w ϓϩμΫγϣϯͰ͸*OTUSPTQFDUJPOΛ௵͢
    w 1FSTJTUFE2VFSZΛ࢖͏

    View Slide

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


    w εΩʔϚ৘ใ͕ਪଌͰ͖ͳ͘ͳΔΘ͚Ͱ͸ͳ͍͜ͱʹ஫ҙ

    View Slide

  75. 1FSTJTUFE2VFSZΛ࢖͏
    ҙਤ͠ͳ͍ΫΤϦΛड͚෇͚ͳ͍
    w ΫϥΠΞϯτ͕ૹ৴͢ΔΫΤϦΛϋογϡ஋ͱ૊Ͱαʔόʔʹొ࿥͓ͯ͘͠
    w ΫϥΠΞϯτ͔Β͸࣮ࡍͷΫΤϦͷ୅ΘΓʹϋογϡ஋ΛૹΔ
    w ΫΤϦͷ಺༰Λ஌ΒΕͣʹࡁΉ
    w ࣄલʹొ࿥͞Ε͍ͯͳ͍ΫΤϦΛ๷͛Δ
    • GraphQL
    ::
    Pro
    : :
    OperationStore


    w ΫϥΠΞϯτϥΠϒϥϦͷ΄ͱΜͲ͕ରԠ͍ͯ͠Δ

    View Slide

  76. ΦϒβʔόϏϦςΟͷ௿Լ
    w (SBQI2-͸୯ҰͷΤϯυϙΠϯτΛ࢖͏
    w POST /graphql


    w 3&45͸Ϧιʔε΍ॲཧ͝ͱʹΤϯυϙΠϯτ͕෼͔Ε͍ͯͨ
    w (SBQI2-ͷ৔߹͸ΞΫηεϩάͰ͸৘ใ͕଍Γͳ͍
    w ฏۉͷϨΠςϯγ΍Τϥʔ཰Λݟͯ΋Կ͕ى͖͍ͯΔ͔Θ͔Βͳ͍

    View Slide

  77. ΦϒβʔόϏϦςΟΛ֬อ͢Δ
    w τϨʔγϯά͢Δ
    w Ϧκϧόͷݺͼग़͠΍*0Λه࿥
    • GraphQL
    ::
    Tracing

    View Slide

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

    View Slide

  79. ·ͱΊ

    View Slide

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

    View Slide