Slide 1

Slide 1 text

1 (SBQI2-࣮ફϊ΢ϋ΢ (SBQI2-ͷબఆͱ࣮ફ5FDINFFWPM !TPOBUBSEͦͳଠ

Slide 2

Slide 2 text

Appify Technologies CTO ͦͳଠ @sonatard

Slide 3

Slide 3 text

3 "QQJGZ w 4IPQJGZͷΞϓϦΛ/P$PEFͰϦϦʔεͰ͖ΔΔαʔϏε w J04ɺ"OESPJE w J04ɺ"OESPJEɺ8FCɺόοΫΤϯυͰ(SBQI2-Λར༻͍ͯ͠·͢ w ࠾༻ w IUUQTBQQJGZJODDPNDBSFFS

Slide 4

Slide 4 text

͸͡Ίʹ

Slide 5

Slide 5 text

5 (SBIQ2-͸ศརͰ͕͢ʜ w (SBQI2-͸ͱͯ΋ศརͰ͢ w ͕ɺཧղ͢Δ͜ͱ͕೉͍͠Ͱ͢ w ࠓ·Ͱͱ͸େ͖͘ҟͳΔύϥμΠϜͰ͋ΔͨΊཧղʹۤ࿑͠·͢ w ͔͠͠ཧղͯ͠ਖ਼͘͠(SBQI2-Λར༻͢Δ͜ͱͰ։ൃޮ཰͸େ෯ʹ্͕Γ·͢ɻ ։ൃޮ཰ ཧղ౓ Ұఆͷཧղ౓Λ௒͑Δͱ େ͖͘͸։ൃޮ཰͕޲্͢Δ

Slide 6

Slide 6 text

6 (SBIQ2-͸ศརͰ͕͢ʜ w (SBQI2-Λཧղ͢Δͱ͖ʹେ੾ͳ͜ͱ͸6OMFBSOJOH͢Δ͜ͱͰ͢ɻ w ৽ٕज़Λطଘٕज़ͷԆ௕Ͱཧղͯ͠͠·͏ͱɺ৽ٕज़͸ຊདྷͷྗΛൃشͰ͖·ͤΜɻ w (SBQI2-ͱ͍͏໊લ͔ͩΒɺ42-ͱࣅͨ΋ͷʁ w ϑϩϯτΤϯυ͕42-ʹ௚઀ΞΫηε͢ΔͨΊͷ΋ͷʁˠ❌ w ࠓ·Ͱ͸3&45Ͱ͜͏΍͍ͬͯͨ͜ͱ͸ɺ(SBQI2-Ͱ΋͜͏΍Δͷ͔ͳʁ w (SBQIߏ଄Λ׆͔ͣ͞ʹ3&45ͷΑ͏ʹJEΛฦ٫ͯ͠͠·͏ˠ❌ w 3&45ͷΑ͏ʹϑϩϯτΤϯυ͸ड͚औͬͨܕΛม׵͍ͯ͘͠ˠ❌ w (SBQI2-ͷػೳͷ໨తΛ͔Βཧղ͢Δ͜ͱ͕େ੾Ͱ͢ɻ

Slide 7

Slide 7 text

7 (SBIQ2-ͱ͸ w جຊ w 0WFSGFUDIͷղফ w ඞཁͳ஋͚ͩΛΫΤϦʔʹهड़ͯ͠औಘ͢ΔͷͰɺ༨ܭͳϑΟϧʔυͷ஋Λऔಘ͠ ͳ͍ͰࡁΉ w 6OEFSGFUDIͷղফ w (SBQIߏ଄ʹͳ͍ͬͯΔͨΊɺϦϨʔγϣϯ͕͋Δ஋͸̍౓ʹऔಘ͢Δ͜ͱ͕Ͱ͖ Δ w εΩʔϚۦಈ։ൃ w εΩʔϚΛݩʹόοΫΤϯυͷίʔυͷੜ੒΍ΫϥΠΞϯταΠυͷΫΤϦʔͷ هड़Λߦ͏

Slide 8

Slide 8 text

εΩʔϚۦಈ։ൃ

Slide 9

Slide 9 text

9 εΩʔϚۦಈ։ൃͷϝϦοτ (SBQI2-4DIFNBΛݩʹؔ࿈͢Δίʔυ͕ੜ੒͢ΔͷͰɺܕͷෆҰக͕ى͖ͳ͍ ࣮૷ྔΛେ෯ʹ࡟ݮͰ͖Δ

Slide 10

Slide 10 text

10 εΩʔϚۦಈ։ൃ (SBQI2-4DIFNBΛݩʹؔ࿈͢Δίʔυ͕ੜ੒͢ΔͷͰɺܕͷෆҰக͕ى͖ͳ͍ w 2VFSZɺΫϥΠΞϯτͷGFUDI͢ΔίʔυɺόοΫΤϯυͷϋϯυϥ SFTPMWFS type Query { node(id: ID!): Node! viewer: User! adminViewer: Admin! }

Slide 11

Slide 11 text

11 εΩʔϚۦಈ։ൃ w (SBQI2-4DIFNBͷఆٛʹ͠ै͍ ੩తղੳ͕Մೳ w -JOUFSͳͲΛࣗ༝ʹ࡞Δ͜ͱ͕ Ͱ͖Δ w (SBQI2-͸DVTUPNEJSFDUJWFͳͲ ͰಠࣗͷϧʔϧΛ෇༩͢Δ͜ͱ͕ Մೳ w ಠࣗϧʔϧʹରͯ͠ͷ੩తղੳ πʔϧ΋࡞Δ͜ͱ͕Ͱ͖Δ w EJSFDUJWFͷষͰޙड़͠·͢

Slide 12

Slide 12 text

12 (SBQI2-εΩʔϚʹΑΔίʔυੜ੒ͷར఺ w େ෯ʹ࣮૷ྔͷ࡟ݮ͕Մೳ 6* 6TFDBTF 3FQPTJUPSZ 6* (SBQI2-͔Β͸ 7JFX.PEFM͕ฦͬͯ͘ΔͷͰͳ͠ ੜ੒͞Εͨ(SBQI2-ΫϥΠΞϯτ ϨΠϠʔ͸6*͚ͩʹͳΓɺ͋ͱ͸ ੜ੒͞Εͨ(SBQI2-ΫϥΠΞϯτ Λݺͼग़͚ͩ͢ʹͳΔ ैདྷͷΞʔΩςΫνϟ (SBQI2-ར༻࣌ͷΞʔΩςΫνϟ

Slide 13

Slide 13 text

13 εΩʔϚۦಈ։ൃͷར఺ w େ෯ʹ࣮૷ྔͷ࡟ݮ͕Մೳ @Composable fun RaffleProductVariantsPage(productID: ShopifyApiId) { val (data, loading, error) = graphql.query( q = RaffleProductVariantsPageQuery(productID) ) when { loading -> { Spinner() } error != null -> { ErrorDialog(error) } else -> { // UI } } } 2VFSZΛ࣮ߦ͢ΔͷΈ query RaffleProductVariantsPage { ɹ ($productID: ID!) { product(id: $productID) { id variants(first: 250) { nodes { id title availableForSale } } } } (SBQI2-ΫΤϦʔ

Slide 14

Slide 14 text

14 (SBQI2-εΩʔϚʹΑΔίʔυੜ੒ͷར఺ w ࣮࣭తʹϓϥοτϑΥʔϜ͝ͱͷڞ௨ԽʹΑΔ࣮૷ͷ࡟ݮͱಉ౳ͷޮՌΛಘΔ w ,..ͳͲͰͷڞ௨Խͱಉ౳ͷޮՌ "OESPJE 6* 6TFDBTF 3FQPTJUPSZ J046* σʔλΞΫηεΛڞ௨Խ ͯ͠ɺ࣮૷Λ࡟ݮ ,.. "OESPJE 6* J046* (SBQI2- ΫϥΠΞϯτ (SBQI2- ΫϥΠΞϯτ ίʔυੜ੒ʹΑΓ ࣮૷Λ࡟ݮ ,..ʹΑΔڞ௨Խ͸,PUMJOͰͷ࣮૷͕ඞཁʹͳΔ͕ɺ ࣗಈੜ੒Ͱ͸౓΋࣮૷͕ෆཁͳͷͰɺΑΓޮՌ͕ظ଴Ͱ͖Δ

Slide 15

Slide 15 text

15 (SBQI2-εΩʔϚʹΑΔίʔυੜ੒ͷར఺ w ڞ௨Խͤͣʹ࣮૷ྔΛݮΒ͢͜ͱʹΑΔߋͳΔར఺ಠཱੑͷ֬อ "OESPJE 6* J046* (SBQI2- ΫϥΠΞϯτ (SBQI2- ΫϥΠΞϯτ J04ͱ"OESPJEͰ ҟͳΔ2VFSZΛॻ͖ ҟͳΔΫϥΠΞϯτΛ ੜ੒Ͱ͖Δ (SBQI2- 2VFSZ (SBQI2- 2VFSZ w ۙ೥.JDSPTFSWJDFTΛத৺ʹ։ൃͷಠཱੑ͕ॏཁࢹ͞Ε͍ͯ·͢ɻ w ڞ௨Խ͸։ൃޮ཰Λ্͛·͕͢ɺݸʑͷ࠷େ։ൃ଎౓Λ཈͑ΔՄೳੑ͕͋Γ·͢ɻ w ྆ํͷϓϥοτϑΥʔϜΛҙ࣮ࣝͯ͠૷͠ͳ͚Ε͹͍͚ͳ͍ w ยํͷ౎߹Ͱɺ΋͏ยํͷ։ൃ͕ਐ·ͳ͍ w ͦͷͨΊ.JDSPTFSWJDFTͰ͸ɺ༷ʑͳ௥Ճͷෛ୲ίετΛड͚ೖΕͨ͏͑ͰݸผͷνʔϜ ͱαʔόΛ༻ҙͯ͠ɺ։ൃ΍σϓϩΠͷಠཱੑΛ֬อ͠·͢ɻ

Slide 16

Slide 16 text

(SBQI2-εΩʔϚʹΑΔίʔυੜ੒ͷར఺ w ΫϥΠΞϯταΠυͰ΋ಉ༷ʹಠཱੑͷ֬อ͸ॏཁͰ͢ɻ w ҟͳΔϓϥοτϑΥʔϜͰॻ͍͍ͯΔݶΓɺ଍ฒΈΛἧ͑ͣϓϥοτϑΥʔϜ͝ͱʹ࠷ దͳॻ͖ํΛͨ͠ํ͕ݸผͰ͸࠷େ଎౓͕ग़·͢ɻ w (SBQI2-͸ΫϥΠΞϯτ͝ͱʹ2VFSZΛॻ͘͜ͱ͕Ͱ͖Δͷ͕ϝϦοτͰ͢ɻ w ڞ௨Խͯ͠͠·͏ͱ͜ͷϝϦοτΛࣦ͍·͢ɻ w 2VFSZͷ౷Ұ͸7JFXʹ΋Өڹ͢ΔͨΊɺ7JFX΋଍ฒΈΛἧ͑Δඞཁ͕Ͱ͖ͯ·͢ɻ w 3&45͸͜ͷΑ͏ͳϝϦοτ͕ݩʑ͋ΔΘ͚Ͱ͸ͳ͍ͷͰɺڞ௨ԽʹΑΔଛࣦ͸গͳ͍ɻ w "QQJGZͰ͸ɺJ04ͱ"OESPJEͷ6*΍(SBQI2-ΫΤϦʔͷ࣮૷͸ಠཱͯ͠ߦͳ͍ͬͯ·͢ɻ 16

Slide 17

Slide 17 text

17 (SBQI2-εΩʔϚʹΑΔίʔυੜ੒ͷར఺ w ݸผʹ࣮૷͢ΔσϝϦοτ͸ɺ࢓༷ͷ౷Ұ͕೉͘͠ͳΔ͜ͱͰ͢ɻ w ͲͪΒͷԸܙ΋ड͚͍ͨͱ͖ʹ͸ɺ'MVUUFS΍3FBDU/BUJWFͰ͢΂ͯΛڞ௨Խ͢Δબ୒ࢶ ΋͋Γ·͢ɻ w ͔͠͠΋ͪΖΜ'MVUUFS΍3FBDU/BUJWFʹ΋՝୊͸͋ΔͷͰɺਖ਼ղ͸͋Γ·ͤΜɻ w ΞʔΩςΫτͷ࣮ྗͷݟͤॴ💪

Slide 18

Slide 18 text

w ڞ௨Խ͢Δ͜ͱͰ։ൃޮ཰Λ্͛Δ͜ͱ͕Ͱ͖·͕͢ɺ։ൃͷಠཱੑΛҡ࣋͢Δ͜ͱ΋ ։ൃ଎౓Λ্͛Δ͏͑Ͱ͸େ੾Ͱ͋ΓɺόϥϯεΛऔΔඞཁ͕͋Γ·͢ɻ (SBQI2-Λར༻͢Δͱ"1*ΫϥΠΞϯτͷ఺Ͱ͸ɺͲͪΒͷԸܙ΋ड͚Δ͜ͱ͕ՄೳͰ ͢ɻ 18 (SBQI2-εΩʔϚʹΑΔίʔυੜ੒ͷར఺ ڞ௨ԽʹΑΔ ޮ཰ੑ ಠཱੑʹΑΔ ։ൃ଎౓ͷ࠷େԽ

Slide 19

Slide 19 text

2VFSZͷεΩʔϚઃܭͱೝূೝՄ

Slide 20

Slide 20 text

20 2VFSZͷεΩʔϚઃܭ type Query { viewer: User! order(orderID: ID!): Order! product(productID: ID!): Product! } type User implements Node { id: ID! orderID: ID! } type Order implements Node { id: ID! productID: ID! } type Product implements Node { id: ID! name: String! } w 3&45ͷΑ͏ͳεΩʔϚ*%Λฦͯ͠ɺͦͷ*%Ͱ࣍ͷ2VFSZΛ࣮ߦ query GetOrderID { viewer { orderID } } query GetProductIDByOrder($orderID: ID!) { order(orderID: $orderID) { productID } } query GetProduct($productID: ID!) { product(productID: $productID) { name } }

Slide 21

Slide 21 text

21 2VFSZͷεΩʔϚઃܭ w 3&45ͷΑ͏ͳεΩʔϚ*%ฦͯ͠ɺͦͷ*%Ͱ࣍ͷ2VFSZΛ࣮ߦ ΫϥΠΞϯτ αʔό (FU0SEFS*% PSEFS*% (FU1SPEVDU*%#Z0SEFS QSPEVDU*% (FU1SPEVDU QSPEVDUOBNF ճͷϥ΢ϯυτϦοϓ͕ ͋Γɺ(SBQI2-ͷϝϦο τΛੜ͔͍ͤͯͳ͍

Slide 22

Slide 22 text

22 2VFSZͷεΩʔϚઃܭ type Query { viewer: User! } type User implements Node { id: ID! order: Order! } type Order implements Node { id: ID! product: Product! } type Product implements Node { id: ID! name: String! } w (SBQIߏ଄Λ׆͔ͨ͠εΩʔϚ w ΦϒδΣΫτΛฦ͢ query GetProduct { viewer { order { product { name } } } } ΫϥΠΞϯτ (FU1SPEVDU 1SPEVDUOBNF αʔό ̍ճͷϥ΢ϯυτϦοϓͰࡁΉ

Slide 23

Slide 23 text

23 2VFSZͷεΩʔϚઃܭ type Query { viewer: User! } type User implements Node { id: ID! order: Order! } type Order implements Node { id: ID! product: Product! } type Product implements Node { id: ID! name: String! } w 3&45ͷΑ͏ͳεΩʔϚ w (SBQIߏ଄Λ׆͔ͨ͠εΩʔϚ type Query { viewer: User! order(orderID: ID!): Order! product(productID: ID!): Product! } type User implements Node { id: ID! orderID: ID! } type Order implements Node { id: ID! productID: ID! } type Product implements Node { id: ID! name: String! } ଞͷUZQFͷ*%Λฦ͍ͯͨ͠Βٙ͏ *%Λฦ͢ͷͰ͸ͳ͘ ΦϒδΣΫτΛฦ͢

Slide 24

Slide 24 text

24 2VFSZͷεΩʔϚઃܭ w (SBQIߏ଄Λ׆͔ͨ͠εΩʔϚ͔Βੜ੒͞ΕͨSFTPMWFSͷ࣮૷ w ਌ͷ*%Λड͚औͬͯɺͦͷ*%ʹैͬͯΦϒδΣΫτΛฦ͢ func (r *queryResolver) Viewer(ctx context.Context) (*domain.User, error) { userID := ctxvalue.UserID(ctx) // ೝূͨ͠UserID user, _ := r.app.GetUser(ctx, userID) return user, nil } func (r *userResolver) Order(ctx context.Context, user *domain.User) (*domain.Order, error) { order, _ := r.app.GetOrderByUserID(ctx, user.ID) return order, nil } func (r *orderResolver) Product(ctx context.Context, order *domain.Order) (*domain.Product, error) { product, _ := r.app.GetProductByOrderID(ctx, order.ID) return product, nil } w ೝূ͸NJEEMFXBSFͰ"VUIPSJ[BUJPOϔομΛݩʹߦ͏͜ͱ͸3&45ͱมΘΒͳ͍ w ೝূͷ࣮૷͸লུ͠·͢

Slide 25

Slide 25 text

25 2VFSZͷεΩʔϚઃܭ w SFTPMWFSͷߟ͑ํ w ਌ͷ*%Λड͚औͬͯɺͦͷ*%ʹैͬͯΦϒδΣΫτΛฦ͢ w ೝূ৘ใΛݩʹฦ͞ͳ͍͜ͱ͕େ੾ w ೝূ৘ใΛݩʹฦ͢ѱ͍ྫ w PSEFSSFTPMWFSͰɺ6TFS͕ೝূ͍ͯ͠Δ*%͔Βฦ͢Α͏ʹ࣮૷ func (r *userResolver) Order(ctx context.Context, user *domain.User) (*domain.Order, error) { userID := ctxvalue.UserID(ctx) // ೝূͨ͠UserID // ਌ͷuser.IDΛ࢖Θͣೝূͨ͠userIDΛ࢖͏ order, _ := r.app.GetOrderByUserID(ctx, userID) return order, nil }

Slide 26

Slide 26 text

26 2VFSZͷεΩʔϚઃܭ w ೝূ৘ใΛݩʹฦ͢ѱ͍ྫPSEFSSFTPMWFSͰ͸ɺ6TFS͕ೝূ͍ͯ͠Δ*%͔Βฦ͢Α͏ʹ࣮૷ func (r *userResolver) Order(ctx context.Context, user *domain.User) (*domain.Order, error) { // Admin͕͜͜ʹ౸ୡ͢ΔͱUserͱͯ͠ೝূ͍ͯ͠ͳ͍ͨΊΤϥʔʹͳͬͯ͠·͏ userID := ctxvalue.UserID(ctx) // ೝূͨ͠UserID // ਌ͷuser.IDΛ࢖Θͣೝূͨ͠userIDΛ࢖͏ order, _ := r.app.GetOrderByUserID(ctx, userID) return order, nil } type Query { viewer: User! adminViewer: Admin! } type User implements Node { id: ID! order: Order! } type Admin implements Node { id: ID! user: User! } type Order implements Node { id: ID! product: Product! } type Product implements Node { id: ID! name: String! } query GetOrder { adminViewer { user { order { #orderΛҾ͘ͱΤϥʔ id } } } } w "ENJO͸؅ཧऀͳͷͰ6TFSͷ0SEFSΛࢀরͰ͖͍͍ͯ͸͕ͣɺΤϥʔ ʹͳΔɻ

Slide 27

Slide 27 text

27 2VFSZͷεΩʔϚઃܭ w ਌ͷ*%Λར༻͢Δਖ਼͍͠ྫ func (r *userResolver) Order(ctx context.Context, user *domain.User) (*domain.Order, error) { // ೝূͨ͠userIDͰ͸ͳ͘ɺ਌ͷuser.IDΛ࢖͏ order, _ := r.app.GetOrderByUserID(ctx, user.ID) return order, nil } type Query { viewer: User! adminViewer: Admin! } type User implements Node { id: ID! order: Order! } type Admin implements Node { id: ID! user: User! } type Order implements Node { id: ID! product: Product! } type Product implements Node { id: ID! name: String! } query GetOrder { adminViewer { user { order { #orderΛҾ͍ͯ΋ΤϥʔʹͳΒͳ͍ id } } } } w 6TFSͷೝূ৘ใ͕ෆཁʹͳͬͨͨΊ"ENJO͕ฦ͢͜ͱ͕Ͱ͖Δ

Slide 28

Slide 28 text

28 2VFSZͷεΩʔϚઃܭ w (SBQI2-ಛ༗ͷศརͳϙΠϯτ w ΫϥΠΞϯτ౎߹ͷϑΟʔϧυͷ௥Ճ͕༰қ w ྫ͑͹ର৅঎඼Λ͓ؾʹೖΓ͍ͯ͠Δ͔Ͳ͏͔ͷϑΟʔϧυ w 1SPEVDUJT'BWPSJUF w ͓ؾʹೖΓঢ়ଶ͸1SPEVDUͱ͸ผͷΦϒδΣΫτ͕؅ཧ͍ͯ͠Δ͕ɺΫϥΠΞϯτ͸ 1SPEVDU͔ΒऔಘͰ͖Δͱ࣮૷͕γϯϓϧʹͳΔɻ w 3&45Ͱ΋1SPEVDUΦϒδΣΫτͷϑΟʔϧυʹ௥Ճ͢Δ͜ͱ͸Ͱ͖Δ͕ɺ1SPEVDUΛ औಘ͢Δϋϯυϥ಺෦Ͱ࣮૷͢Δඞཁ͕͋Δɻ·ͨQSPEVDUऔಘͷͨͼʹඞͣ JT'BWPSJUFʹΞΫηε͢ΔͨΊύϑΥʔϚϯε͕མͪΔɻ w (SBQI2-ͳΒJT'BWPSJUFઐ༻ͷSFTPMWFSΛੜ੒Ͱ͖ΔͷͰطଘ࣮૷ʹӨڹΛ༩͑ͣؾܰʹ ௥ՃՄೳɻ·ͨΫϥΠΞϯτ͸ෆཁͳΒ2VFSZʹ௥Ճ͠ͳ͚Ε͹͍͍ͷͰύϑΥʔϚϯε ΋໰୊ͳ͍ɻ͞Βʹطଘͷ2VFSZ͸JT'BWPSJUFΛҾ͍͍ͯͳ͍ͷͰԼҐޓ׵ੑ΋ؾʹͳΒ ͳ͍ɻ w ͜ͷΑ͏ʹ(SBQI2-͸ΫϥΠΞϯτ౎߹ͷϑΟʔϧυͷϋʔυϧ͕ͱͯ΋௿͍ɻ type Query { viewer: User! } type User implements Node { id: ID! order: Order! } type Order implements Node { id: ID! product: Product! } type Product implements Node { id: ID! name: String! // User͕͓ؾʹೖΓ͍ͯ͠Δ͔ isFavorite: Boolean! } // ಠཱͨ͠resolver func (r *productResolver) IsFavorite(ctx context.Context, obj *domain.Product) (bool, error) { userID := ctxvalue.UserID(ctx) isFavorite, _ := r.app.IsFavoriteProductByUserID(ctx, obj.ID, userID) return isFavorite, nil }

Slide 29

Slide 29 text

29 2VFSZͷεΩʔϚઃܭ w ઌ΄Ͳೝূ৘ใΛݩʹ஋Λฦ͞ͳ͍ํ͕ྑ͍ͱݴ͕ͬͨɺ QSPEVUJT'BWPSJUFͷΑ͏ʹೝূ৘ใΛݩʹฦͨ͠ํ͕ྑ͍͜ͱ΋ ͋Δ w ௨ৗͷΦϒδΣΫτͷϦϨʔγϣϯʹج͖ͮ஋Λฦ͢৔߹ ͱɺ͜ͷΑ͏ʹΫϥΠΞϯτͷͨΊʹಛผͳϑΟʔϧυΛ༻ ҙͨ͠৔߹ͷҧ͍Λ֮ࣗ͠ɺೝূ৘ใͷར༻͸ޙऀ͚ͩʹݶ ఆ͢ΔΑ͏ؾΛ෇͚Δ͜ͱ͕େ੾Ͱ͢ɻ type Query { viewer: User! } type User implements Node { id: ID! order: Order! } type Order implements Node { id: ID! product: Product! } type Product implements Node { id: ID! name: String! // User͕͓ؾʹೖΓ͍ͯ͠Δ͔ isFavorite: Boolean! }

Slide 30

Slide 30 text

30 2VFSZͷεΩʔϚઃܭ w !SPMFEJSFDUJWFʹΑΔ3PMFͷ੍ݶ w 6TFSೝূΛར༻͍ͯ͠Δ͜ͱ͸࣮૷Λݟͳ ͍ͱΘ͔Βͳ͔͕ͬͨɺΫϥΠΞϯτͷΤ ϯδχΞ͸εΩʔϚͰϑΟʔϧυͷݖݶΛ ֬ೝՄೳʹͳΔɻ w "ENJO͔Βͷ࣮ߦ͸JT'BWPSJUFSFTPMWFSͷ࣮ ߦલʹΤϥʔ type Product implements Node { id: ID! name: String! ɹɹ // UserͷΈ࣮ߦͰ͖Δ͜ͱΛεΩʔϚͰදݱ isFavorite: Boolean! @role(roles: [USER]) } # directiveͷఆٛ enum Role { ADMIN USER } directive @role(roles: [Role!]!) on FIELD_DEFINITION // Ҿ਺roles͸isFavoriteʹࢦఆͨ͠roles͕౉ͬͯ͘Δ func (r *Role) Role(ctx context.Context, _ interface{}, next graphql.Resolver, roles []domain.Role) (interface{}, error) { myRoles, _ := ctxvalue.Roles(ctx) // ೝূͨ͠RoleΛऔಘ if !myRoles.HasRole(roles) { // ೝূͨ͠Role͕ϑΟʔϧυʹࢦఆ͞Ε͍ͯͳ͔ͬͨΒΤϥʔ fCtx := graphql.GetFieldContext(ctx) return nil, fmt.Errorf("field: %v, roles want=%v, get=%v", fCtx.Path(), roles, myRoles) } return next(ctx) }

Slide 31

Slide 31 text

31 2VFSZͷεΩʔϚઃܭ w 3PMFͷϝϦοτ w ΞΫηε͍ͯ͠Δ3PMFΛεΩʔϚͰදݱ͢Δ͜ͱͰɺεΩʔϚͷϝϯςφϯεੑ͕޲্͢Δ w ྫ͑͹"QQJGZͰ͸ w 6TFS͕ࢦఆ͞Ε͍ͯΔͱΞϓϦ͔ΒΞΫηε͍ͯ͠Δ͜ͱ͕Θ͔Δ w ΞϓϦ͸ԼҐޓ׵ੑΛҡ࣋͢Δ͜ͱ͕ඞཁͳͷͰɺJT'BWPSJUFϑΟʔϧυ͸ԼҐޓ׵͕ͳ͍ มߋ΍࡟আ͸Ͱ͖ͳ͍ w "ENJO͸8FCͷ؅ཧը໘͔ΒΞΫηε͍ͯ͠Δ͜ͱ͕Θ͔Δ w 8FC͸αʔόͷมߋͱಉ࣌ʹमਖ਼ΛσϓϩΠ͢Ε͹Α͍ͷͰɺԼҐޓ׵ੑΛकΔඞཁ͕ͳ ͍ɻݹ͍ϑΟʔϧυ͸࡟আ͕Մೳɻ type Product implements Node { id: ID! name: String! ɹɹ // UserͷΈ࣮ߦͰ͖Δ͜ͱΛεΩʔϚͰදݱ isFavorite: Boolean! @role(roles: [USER]) secretID: ID! @role(roles: [Admin]) }

Slide 32

Slide 32 text

32 2VFSZͷεΩʔϚઃܭ w 3PMFͷ஫ҙ఺ w 3PMF͸ηΩϡϦςΟରࡦʹ͸ͳΒͳ͍৔߹͕͋Δ w 3PMFΛ͚͍ͭͯΔ͔Βͱ͍ͬͯର৅ϑΟʔϧυΛऔಘ͢Δͷʹೝূ৘ใΛ࢖͍ͬͯΔͱ͸ ݶΒͳ͍ w ͦͷ৔߹͸ɺಉҰϩʔϧͷҟͳΔϢʔβ͸ΞΫηεͰ͖ͯ͠·͏ type Product implements Node { id: ID! name: String! secretID: ID! @role(roles: [Admin]) }

Slide 33

Slide 33 text

33 ೝՄ w ΦϒδΣΫτ΁ͷQFSNJTTJPOͷ؅ཧ w εΩʔϚͷऔಘ͸ೝূ৘ใΛؚΊͳ͍ํ͕ྑ͍ͱݴ͕ͬͨɺ͜Ε͚ͩͰ͸ηΩϡϦςΟʹ໰୊ ͕͋Δ w ҎԼͷεΩʔϚͰ͸ɺ঎඼ͷϨϏϡʔίϝϯτΛͨ͠6TFSͷ1SJWBDZ৘ใʹ୭Ͱ΋ΞΫηε͢ Δ͜ͱ͕Ͱ͖Δ w QSPEVDUSFWJFX$PNNFOUVTFSQSJWBDZFNBJM type User implements Node { id: ID! privacy: UserPrivacy! @role(roles: [USER, ADMIN]) } type UserPrivacy implements Node { id: ID! email: String! } type Product implements Node { id: ID! name: String! reviewComment: ReviewComment! } type ReviewComment implements Node { id: ID! text: String! user: User! @role(roles: [USER, ADMIN]) }

Slide 34

Slide 34 text

34 ೝՄ w 1FSNJTTJPOEJSFDUJWF w 1FSNJTTJPOEJSFDUJWFʹ͸ɺ64&3ͰΞΫηεͨ͠ͱ͖ʹ08/&3Ͱͳ͍ͱΤϥʔʹͳΔ͜ͱ͕ એݴ͞Ε͍ͯΔɻ w 3PMF͸ϑΟʔϧυ͕ͩͬͨQFSNJTTJPO͸ܕʹࢦఆ͢ΔɻܕͷΦϒδΣΫτ͕ฦ͞ΕΔͱ͖ʹ ඞͣೝূͷ࣮૷ίʔυ͕࣮ߦ͞ΕΔɻ࣮૷͸লུ͠·͢ɻ input Permission { role: PermittedRole! type: PermittedType! } enum PermittedRole { USER ADMIN } enum PermittedType { "USER: ର৅ϦιʔεΛอ࣋͢ΔΞϓϦར༻ऀɻADMIN: ର৅ϦιʔεΛอ࣋͢Δ؅ཧऀɻ" OWNER "USER: ৅Ϧιʔεͱಉ͡ΞϓϦΛར༻͍ͯ͠ΔΞϓϦར༻ऀશһɻADMIN: ର৅Ϧιʔεͱಉ͡ΞϓϦͷ؅ཧऀશһɻ" MEMBER } directive @permission(permissions: [Permission!]!) on FIELD_DEFINITION | OBJECT | INTERFACE type UserPrivacy implements Node @permission(permissions: [{role: USER, type: OWNER}]) { id: ID! email: String! }

Slide 35

Slide 35 text

35 ೝՄ w εΩʔϚۦಈ։ൃʹΑΓQFSNJTTJPOEJSFDUJWFΛεΩʔϚͰදݱ͢Δ͜ͱͰɺΫϥΠΞϯταΠ υ͸ೝূ৘ใΛεΩʔϚͰ֬ೝ͢Δ͜ͱ͕Ͱ͖Δɻ w ผ్υΩϡϝϯτͷ࡞੒΍࣮૷ͷத਎Λ֬ೝ͢Δඞཁ͕ͳ͍ɻ w ·ͨೝূͷ࣮૷๨Ε͸஫ҙ͠ͳ͍ͱൃੜͯ͠͠·͏͕ɺ(SBQI2-εΩʔϚΛϨϏϡʔ͢Δ͜ͱͰ อূͰ͖Δɻ w ݸผͷ࣮૷ΛϨϏϡʔ͢ΔΑΓ΋҆શੑ͕ߴ͘ɺઃఆՕॴ΋໌֬Ͱ͋Δɻ w ·ͨ(SBQI2-ͷεΩʔϚΛ੩తղੳ͢Δ͜ͱͰɺQFSNJTTJPOEJSFDUJWFͷ͚ͭ๨ΕͳͲΛݕग़͢ Δ͜ͱ΋ՄೳʹͳΔɻ w SFTPMWFSͷ(SBQIߏ଄ʹैͬͨ஋ͷऔಘͱQFSNJTTJPOEJSFDUJWFʹΑΔೝՄͷ࢓૊Έ͕෼཭͢Δ͜ ͱͰɺόοΫΤϯυίʔυͷ։ൃମݧ΋େ෯ʹ޲্͠·͢ɻ w όοΫΤϯυϩδοΫ͸஋ͷऔಘʹूத͢Ε͹ྑ͍ͨΊɻ

Slide 36

Slide 36 text

36 ೝՄ w SPMFEJSFDUJWF΍QFSNJTTJPOEJSFDUJWFͷΑ͏ͳ΋ͷ͸ϑϨʔϜϫʔΫʹΑͬͯ͸༧Ί༻ҙ͞Ε͍ͯ Δ৔߹΋͋ΔͷͰௐ΂ͯΈ͍ͯͩ͘͞ɻBVUIEJSFDUJWFͳͲʁ w ·ͣ͸ͦΕΛ࢖ͬͯΈͯɺෆ଍͍ͯ͠Δ৔߹ʹ͸ಠࣗʹ࣮૷Λݕ౼ͯ͠Έ͍ͯͩ͘͞ɻ

Slide 37

Slide 37 text

2VFSZͷجຊతͳεΩʔϚઃܭͷଓ͖

Slide 38

Slide 38 text

38 2VFSͷεΩʔϚઃܭ w *%͔ΒΦϒδΣΫτΛऔಘ͢Δํ๏ w (SBQI2-Ͱ͸(SBQIߏ଄ΛݩʹΦϒδΣΫτΛऔಘ͢Δͱݴ͍·͕ͨ͠ɺ*%Λࢦఆ͠ ͯΦϒδΣΫτΛฦ͍ͨ͜͠ͱ͕͋Γ·͢ɻ w ྫ͑͹ɺ঎඼Ұཡը໘͸*%͸ෆཁͰ͕͢ɺ͔ͦ͜Β঎඼ৄࡉը໘ʹҠಈͨ͠Β঎඼ *%͔Β঎඼ΛҾ͘ඞཁ͕͋Γ·͢ɻ w 3&45ͷͱ͖͸ΦϒδΣΫτ͝ͱʹ"1*Λ༻ҙ͢Δ͜ͱ͕ҰൠతͰͨ͠ɻ w QSPVEVDUJE w (SBQI2-Ͱ͸ΦϒδΣΫτ͝ͱͷΫΤϦʔΛ༻ҙ͠ͳ͍͜ͱ͕ҰൠఆͰ͢ɻ w ୅ΘΓʹOPEFΫΤϦʔΛ༻ҙ͠·͢ɻ w 3FMBZͷ(SBQI2-4FSWFS4QFDJ fi DBUJPOʹఆٛ type Query { // ҎԼͷΑ͏ʹ͢ΔͷͰ͸ͳ͘ product(productID: ID!): Product! order(orderID: ID!): Product! // ҎԼͷΑ͏ʹ͢Δ // product΋order΋nodeͰऔಘ node(id: ID!): Node! }

Slide 39

Slide 39 text

39 2VFSͷεΩʔϚઃܭ w OPEFJOUFSGBDF type Query { node(id: ID!): Node! } interface Node { id: ID! @goField(forceResolver: true) } query GetProduct($productID: ID!) { node(id: $productID) { ... on Product { id name } } } w ͜ΕΛ࣮૷͢ΔͨΊʹ͸ɺ*%͔ΒͲͷΦϒδΣΫτ͔Λ൑ผͰ͖Δඞཁ͕͋Γ·͢ɻ w 4IPQJGZͳͲ͸ҎԼͷΑ͏ͳ*%ܗࣜΛ࠾༻͍ͯ͠·͢ɻHJETIPQJGZ1SPEVDU

Slide 40

Slide 40 text

40 2VFSͷεΩʔϚઃܭ w BMJBT w OPEFRVFSZΛ࢖༻͚ͨͩͩ͠ͱΫϥΠΞϯτଆͷίʔυੜ੒ͰɺOPEFͱ͍͏ϑΟʔ ϧυʹͳͬͯ͠·͏ͨΊBMJBTΛࢦఆ͢ΔͱQSPEVDUͱͳΓࣗવͳܗʹͳΓ·͢ɻ query GetProduct($productID: ID!) { node(id: $productID) { ... on Product { id name } } } query GetProduct($productID: ID!) { product: node(id: $productID) { ... on Product { id name } } }

Slide 41

Slide 41 text

41 2VFSͷεΩʔϚઃܭ w VOJPOͱJOUFSGBDF w ͕࣌ؒͳ͍ͨΊޙ೔ࢿྉ௥Ճ͠·͢

Slide 42

Slide 42 text

42 2VFSͷεΩʔϚઃܭ w Χʔιϧϕʔεͷϖʔδωʔγϣϯ࢓༷ w 3FMBZDVSTPSDPOOFDUJPOTQFDJ fi DBUJPO w ༷ʑͳͱ͜ΖͰઆ໌͞Ε͍ͯΔͱࢥ͏ͷͰجຊతͳ࿩͸লུ͠·͢ɻ w ࢓༷ॻʹΑΔͱ3FMBZʹ͸͍͔ͭ͘ͷ࢓༷͕ଘࡏ͢Δɻ w 3FMBZ$MBTTJD w 3FMBZ-FHBDZ w 3FMBZ.PEFSO w ͔ͦ͠͠ΕͧΕͷઆ໌͕࢓༷ʹॻ͔Ε͍ͯͳ͍ͨΊৄࡉ͸ෆ໌

Slide 43

Slide 43 text

43 2VFSͷεΩʔϚઃܭ w چ3FMBZ࢓༷ 3FMBZ$MBTTJD 3FMBZ-FHBDZ type Query { users(first: Int, after: String, last: Int before: String): UserConnection! } type User implements Node { id: ID! } type UserConnection { pageInfo: PageInfo! edges: [UserEdge!]! } type UserEdge { cursor: String! node: User! } type PageInfo { hasNextPage: Boolean! hasPreviousPage: Boolean! }

Slide 44

Slide 44 text

44 2VFSͷεΩʔϚઃܭ w 3FMBZ.PEFSOͰ͸ɺ1BHF*OGPʹTUBSU$VSTPSͱFOE$VSTPS͕௥Ճ͞Εͨɻ w 6TFS&EHFͷDVSTPS࢖Θͳ͘ͳͬͨ type PageInfo { startCursor: String! endCursor: String! hasNextPage: Boolean! hasPreviousPage: Boolean! } type PageInfo { hasNextPage: Boolean! hasPreviousPage: Boolean! } type UserEdge { // ෆཁ cursor: String! node: User! } 3FMBZ.PEFSO 3FMBZ$MBTTJD

Slide 45

Slide 45 text

45 2VFSͷεΩʔϚઃܭ w 3FMBZ.PEFSOͰ͸ɺ6TFS&EHFͷDVSTPS࢖Θͳ͘ͳͬͨ͜ͱͰ৽ͨͳ೿ൊͷ୆಄ w FEHFT࢖ΘͣOPEFTΛ༻ҙ͢Δɻ w ͔͜͠͠Ε͸3FMBZͷTQFDʹ͸ॻ͍͍ͯͳ͍ɻ w 4IPQJGZ"1*΍(SBQI2-"1*͸ͪ͜Β΋ରԠ͍ͯ͠Δɻ type UserConnection { pageInfo: PageInfo! edges: [UserEdge!]! // cursor࢖Θͳ͍ͳΒedges͸ෆཁͰ nodes: [User!]! // ͜ΕͰྑ͍ͷͰ͸ʁ } type UserEdge { cursor: String! // ࢖Θͳ͍ node: User! }

Slide 46

Slide 46 text

46 2VFSͷεΩʔϚઃܭ w OPEFTͷϝϦοτ w ड͚औͬͨϨεϙϯεΛͦͷ··ର৅ͷΦϒδΣΫτͷ഑ྻͱͯ͠ѻ͏͜ͱ͕Ͱ͖Δɻ w &EHFͩͱ٧Ίସ͑࡞ۀ͕ඞཁɻ w ΫϥΠΞϯτͰ͸ม׵ॲཧΛ͠ͳ͍ͷͰ͋·ΓؾʹͳΒͳ͍͕ɺόοΫΤϯυͰ ͸υϝΠϯϩδοΫͷ࣮ݱʹม׵͕͔ܽͤͳ͍ɻ type UserConnection { pageInfo: PageInfo! edges: [UserEdge!]! // cursor࢖Θͳ͍ͳΒedges͸ෆཁͰ nodes: [User!]! // ͜ΕͰྑ͍ͷͰ͸ʁ } type UserEdge { cursor: String! // ࢖Θͳ͍ node: User! }

Slide 47

Slide 47 text

47 2VFSͷεΩʔϚઃܭ w OPEFTͷσϝϦοτ w 044͕3FMBZͷ࢓༷ʹࡌ͍ͬͯͳ͍OPEFTʹ͸ରԠ͍ͯ͠ͳ͍ɻ w "QPMMPʹ͸ϖʔδωʔγϣϯͷΩϟογϡ࣮૷Λޮ཰తʹߦ͏ SFMBZ4UZMF1BHJOBUJPOͱ͍͏ϢʔςΟϦςΟؔ਺͕༻ҙ͞Ε͍ͯΔ͕ɺ͜Ε͸ OPEFTʹ͸ରԠ͍ͯ͠ͳ͍ɻ w ࢓༷ͱͯ͠໌֬ʹͯ͠΄͍͕͠ଘࡏ͠ͳ͍ɻ w 4IPQJGZ΍(SBQI2-ʹOPEFT͕࠾༻͍ͯ͠Δ͕ɺ'BDFCPPLࣾ಺ͰͲ͏ͳ͍ͬͯΔ͔ Θ͔Βͳ͍ɻ64ͷΤϯδχΞͷதͰޱ఻Ͱ఻Θ͍ͬͯΔงғؾ͕͋Γਏ͍ɻ type UserConnection { pageInfo: PageInfo! edges: [UserEdge!]! // cursor࢖Θͳ͍ͳΒedges͸ෆཁͰ nodes: [User!]! // ͜ΕͰྑ͍ͷͰ͸ʁ } type UserEdge { cursor: String! // ࢖Θͳ͍ node: User! }

Slide 48

Slide 48 text

48 2VFSZͷεΩʔϚઃܭͱೝূೝՄ w Χʔιϧϕʔεͷϖʔδωʔγϣϯ·ͱΊ w ݱࡏ͸ɺ3FMBZ.PEFSOʹै͏͜ͱ͕҆શ w ͔͠͠ݱ࣮తʹ͸3FMBZ.PEFSOͷ&EHFTΛ࢖͏͜ͱΑΓ΋OPEFTͷํ͕࣮૷͕γϯϓϧʹͳΔ ͷͰɺͪ͜ΒΛ࠾༻͢Δ͜ͱ΋Մೳ w ඇඪ४ͳͷͰҰఆͷϦεΫΛड͚ೖΕΔඞཁ͕͋Δ

Slide 49

Slide 49 text

49 2VFSZͷεΩʔϚઃܭͱೝূೝՄ w εΩʔϚઃܭ·ͱΊ w Ҏ্ͷج൫͕੔͍ɺཧղ͕Ͱ͖Δͱ(SBQI2-ͷόοΫΤϯυ։ൃ͸γϯϓϧʹͳΓ·͢ɻ w (SBQIߏ଄ͰΦϒδΣΫτΛฦ͢ w 3&45Ͱ*%Λฦ͍ͯͨ͠ͱ͜ΖΛɺΦϒδΣΫτʹ͢Δ w ΦϒδΣΫτؒͷϦϨʔγϣϯΛઃܭ͢Δ͜ͱ͸3&45ͱมΘΒͳ͍ w ஋औಘͷ࣮૷ޙʹSPMFɺQFSNJTTJPOEJSFDUJWFΛઃఆ͢Δ w 3&45ͱ͸ҟͳΓ஋औಘͱೝՄΛ෼཭ͯ͠ɺ஋औಘʹϑΥʔΧεͨ͠γϯϓϧͳ࣮૷͕Մೳ w OPEFɺ$POOFDUJPOʹै͏ w Ұൠతͳ࢓༷͕ఆٛ͞Ε͍ͯΔ

Slide 50

Slide 50 text

.VUBJUPOͷεΩʔϚઃܭ

Slide 51

Slide 51 text

51 .VUBJUPOͷεΩʔϚઃܭ w େ͖͘͸3&45ͱมΘΒͳ͍ w 3&45ΑΓ΋31$Λҙࣝͨ͠ઃܭʹͳΔ w H31$΍+40/31$ͷํ͕ΑΓࣅ͍ͯΔ w (SBQI2-ͷNVUBJUPOͰ͸ͳ͘3&45Ͱ͍͍ͷͰ͸ʁ w Ωϟογϡͷߋ৽ͷͨΊʹNVUBUJPO͸ඞཁ w (SBQI2-ͷ༷ʑͳػೳΛ2VFSZͱ౷Ұͯ͠࢖͑ΔͷͰศར w EJSFDUJWFͳͲ

Slide 52

Slide 52 text

52 .VUBJUPOͷεΩʔϚઃܭ w *OQVUͱ1BZMPBEܕΛ༻ҙ͢Δ w *OQVUʹ͸UZQFΛ౉͢͜ͱ͸Ͱ͖ͳ͍ w ͜ΕʹΑΓ҆қʹUZQFΛJOQVUͱͯ͠࠶ར༻͢Δ͜ͱΛ๷͍Ͱ͍Δ w ྫ͑͹6TFSͷҰ෦ͷ৘ใΛߋ৽͢ΔNVUBUJPOʹؙ͝ͱ6TFSΛ౉ͯ͠͠·͏ͳͲ type Mutation { addFavoriteProduct(input: AddFavoriteProductInput!): AddFavoriteProductPayload! @role(roles: [USER]) } input AddFavoriteProductInput { productID: ID! @id(kind: "Product") } type AddFavoriteProductPayload { product: Product! }

Slide 53

Slide 53 text

53 .VUBJUPOͷεΩʔϚઃܭ w 1BZMPBE͸༻ҙͤͣɺ௚઀ର৅ͷΦϒδΣΫτΛฦ͢͜ͱ΋Մೳ͕͓ͩ͢͢Ί͠ͳ͍ɻ w কདྷతʹଞͷϨεϙϯεΛฦͨ͘͠ͳͬͨ৔߹ʹରԠͰ͖ͳ͍ͨΊɻ type Mutation { addFavoriteProduct(input: AddFavoriteProductInput!): AddFavoriteProductPayload! @role(roles: [USER]) # ҎԼ΋Մೳ͕͓ͩ͢͢Ί͠ͳ͍ addFavoriteProduct(input: AddFavoriteProductInput!): Product! @role(roles: [USER]) } input AddFavoriteProductInput { productID: ID! @id(kind: "Product") } type AddFavoriteProductPayload { product: Product! }

Slide 54

Slide 54 text

54 .VUBJUPOͷεΩʔϚઃܭ w 1BZMPBE͸ɺΫϥΠΞϯτ͕͜ͷNVUBUJPOʹΑΓߋ৽ͨ͠ΦϒδΣΫτΛऔಘͰ͖ΔΑ ͏ʹ͢Δɻ w ΫϥΠΞϯτ͸ɺαʔόͰߋ৽ͨ͠৘ใΛݩʹΫϥΠΞϯτΩϟογϡΛߋ৽͢ΔͨΊ ʹ1BZMPBEΛར༻͢Δɻ w ·ͨNVUBUJPOͷฦΓ஋΋2VFSZʹͳ͍ͬͯΔͷͰɺΫϥΠΞϯτ͸޷͖ͳϨεϙϯε ͚ͩऔಘՄೳʹͳ͍ͬͯΔɻ type Mutation { addFavoriteProduct(input: AddFavoriteProductInput!): AddFavoriteProductPayload! } input AddFavoriteProductInput { productID: ID! @id(kind: "Product") } type AddFavoriteProductPayload { product: Product! } mutation AddFavoriteProduct($productID: ID!) { addFavoriteProduct(input: { productID: $productID }) { # QueryͳͷͰ޷͖ͳ஋͚ͩऔಘՄೳ product { id name # ΫϥΠΞϯτ͸isFavoriteͷมߋͨͨ͠ΊΩϟογϡߋ৽Λ͢Δɻ isFavorite } } }

Slide 55

Slide 55 text

55 .VUBJUPOͷεΩʔϚઃܭ w ࣮͸ΫϥΠΞϯτΩϟογϡͷࢹ఺ͰɺҎԼͷNVUBUJPO͸׬ᘳͱ͸ݴ͑ͳ͍ɻ w ΋͠6TFSʹ͸GBWPSJUF1SPEVDUTΫΤϦʔͱ͍͏6TFSͷ͓ؾʹೖΓ঎඼ҰཡΛऔಘ͢ΔΫ ΤϦʔ͕ଘࡏ͢Δ৔߹ w BEE'BWPSJUF1SPEVDU࣮ߦͨ͠ͱͯ͠΋ɺ1BZMPBEͰGBWPSJUF1SPEVDUTΫΤϦʔΛऔಘ͠ ͍ͯͳ͍ͨΊΩϟογϡߋ৽͕͞Εͳ͍ɻ type User implements Node { id: ID! favoriteProducts: [Product!]! } mutation AddFavoriteProduct($productID: ID!) { addFavoriteProduct(input: { productID: $productID }) { product { id name # ΫϥΠΞϯτ͸isFavoriteͷมߋͨͨ͠ΊΩϟογϡߋ৽Λ͢Δɻ isFavorite } } }

Slide 56

Slide 56 text

56 .VUBJUPOͷεΩʔϚઃܭ w 1BZMPBEͰGBWPSJUF1SPEVDUTΫΤϦʔΛऔಘ͍ͯ͠ͳ͍ͨΊΩϟογϡߋ৽͕͞Εͳ͍໰ ୊ͷղܾࡦ w 1BZMPBEʹ6TFSΛ௥Ճͯ͠ɺϨεϙϯεͷΫΤϦʔͰGBWPSJUF1SPEVDUTΛऔಘ͢Δ type User implements Node { id: ID! favoriteProducts: [Product!]! } mutation AddFavoriteProduct($productID: ID!) { addFavoriteProduct(input: { productID: $productID }) { product { id name isFavorite } user { id # Ωϟογϡߋ৽ favoriteProducts { id name } } } } type AddFavoriteProductPayload { product: Product! user: User! // ௥Ճ }

Slide 57

Slide 57 text

57 .VUBJUPOͷεΩʔϚઃܭ w 1BZMPBEͰGBWPSJUF1SPEVDUTΫΤϦʔΛऔಘ͍ͯ͠ͳ͍ͨΊΩϟογϡߋ৽͕͞Εͳ͍໰ ୊ͷղܾࡦ w NVUBUJPO࣮ߦޙʹGBWPSJUF1SPEVDUTΛSFGFUDI͢Δɻ w "QPMMP$MJFOUʹ͸͜ͷͨΊͷػೳ͕ଘࡏ͍ͯ͠·͢ɻ type User implements Node { id: ID! favoriteProducts: [Product!]! } query FavoriteProducts { viewer { favoriteProducts { id name } } }

Slide 58

Slide 58 text

58 .VUBJUPOͷεΩʔϚઃܭ w 1BZMPBEͰGBWPSJUF1SPEVDUTΫΤϦʔΛऔಘ͍ͯ͠ͳ͍ͨΊΩϟογϡߋ৽͕͞Εͳ͍໰ ୊ͷղܾࡦ w ΩϟογϡΛखಈͰߋ৽͢Δ w (SBQI2-Ωϟογϡ͸ΫϥΠΞϯταΠυͰ࣮૷͢Δ͜ͱͰɺ޷͖ʹ஋Λߋ৽͢ Δ͜ͱ͕Ͱ͖·͢ɻ w ͔͠͠ݸਓతʹ͸͋·Γ͓קΊ͠·ͤΜɻ w ϝϯςφϯε͕௿Լ͢ΔͷͰɺಛผͳύϑΥʔϚϯε͕ඞཁͰͳ͍ݶΓ͸͔ͷ ղܾࡦΛ͓͢͢Ί͠·͢ɻ

Slide 59

Slide 59 text

59 .VUBJUPOͷεΩʔϚઃܭ w ·ͱΊ w NVUBUJPOʹ͸ɺJOQVUͱฦΓ஋ͷͨΊͷ1BZMPBEܕΛఆٛ͢Δɻ w ΫϥΠΞϯτΩϟογϡߋ৽ͷͨΊʹɺNVUBUJPOͰߋ৽ͨ͠஋Λ1BZMPBEͰฦ͢ɻ w ߋ৽ͷ৔߹͸ɺߋ৽ͨ͠ΦϒδΣΫτΛJEͱͱ΋ʹฦ͢ɻ w ৽ن࡞੒ɺ࡟আͷ৔߹͸ w ߋ৽ର৅ͷΦϒδΣΫτΛࢀর͍ͯ͠Δ͢΂ͯͷ਌ͷΦϒδΣΫτΛฦ͢ w εΩʔϚͰ͸ରԠͤͣɺΫϥΠΞϯτ͕3FGFUDI͢Δ w εΩʔϚͰ͸ରԠͤͣɺΫϥΠΞϯτ͕Ωϟογϡߋ৽Λ͢Δ

Slide 60

Slide 60 text

4DBMBSͷ׆༻

Slide 61

Slide 61 text

61 4DBMBS w 4DBMBS w *E TUSJOH fl PBU *OU w $VTUPN4DBMBS w %BUF5JNF w 63- w ϑϨʔϜϫʔΫʹΑΔ͕(SBQI2-ͷܕͱݴޠͷܕΛόΠϯσΟϯάͰ͖Δ w ྫ͑͹HRMHFOͰ%BUF5JNFܕΛ࡞੒ͯ͠ɺUJNF5JNFܕΛόΠϯσΟϯά͢Δͱɺ (SBQI2-ͱͯ͠%BUF5JNFܕΛड͚औΔ৔߹͸ɺUJNF5JNFܕΛฦͤ͹͍͍ w +TPOͱͷରԠ͸ݸผʹ࣮૷Մೳ w ΫϥΠΞϯταΠυͷBQPMMPJPT΍BQPMMPBOESPJEͰ΋ಉ༷ w 8FCͷ"QPMMPΫϥΠΞϯτʹ͸ͳ͍ʁ

Slide 62

Slide 62 text

EJSFDUJWFͷ׆༻

Slide 63

Slide 63 text

63 EJSFDUJWFͷ׆༻ w ඪ४࢓༷ͷEJSFDUJWF w EFQSFDBUFE w %FQSFDBUFEʹͳͬͨϑΟʔϧυʹࢦఆ͢Δɻ w ΫϥΠΞϯταΠυ͸ɺ2VFSZ͔Βίʔυੜ੒͢Δͱ͖ʹܯࠂͯ͘͠ΕΔ΋ͷ΋͋ Γ·͢ɻ w ܯࠂ͠ͳ͍৔߹͸IUUQTHJUIVCDPNHRMHPEFQSFDBUFERVFSZΛར༻͢Δͱݕग़ Ͱ͖·͢ɻ w TQFDJ fi FE#Z w $VTUPN4DBMBSͷ࢓༷Λදݱ͢Δɻ

Slide 64

Slide 64 text

64 EJSFDUJWFͷ׆༻ w $VTUPNEJSFDUJWF w "QQJGZͰ׆༻͍ͯ͠ΔEJSFDUJWF w JEEJSFDUJWF w ,JOEʹࢦఆͨ͠*%Ҏ֎Λ౉͢ͱΤϥʔʹͳΔ w WBMJEBUJPOEJSFDUJWF w 1BUUFSOʹࢦఆͨ͠৚݅ʹҰக͠ͳ͍஋Λ౉͢ͱΤϥʔ ύλʔϯϧʔϧ͸ɺIUUQTHJUIVCDPNHPQMBZHSPVOEWBMJEBUPSͷ΋ͷΛར༻ɻ input AddFavoriteProductInput { productID: ID! @id(kind: "Product") } input CreateAdminInput { name: String! @validate(pattern: “required,min=1,max=100”) }

Slide 65

Slide 65 text

65 EJSFDUJWFͷ׆༻ w "QQJGZͰ׆༻͍ͯ͠ΔEJSFDUJWF w BENJO"QQMJDBUJPO.FNCFSEJSFDUJWF w ࢦఆͨ͠ϑΟʔϧυͷ"QQMJDBUJPOʹॴଐ͍ͯ͠ͳ͍"ENJO͕࣮ߦ͢ΔͱΤϥʔ w ੬ऑੑΛ๷͙ w Ԡ༻ྫͱͯ͠ɺJOQVUͷBQQMJDBUJPO*%Λࢦఆ͍ͯ͠Δ৔߹ʹ !BENJO"QQMJDBUJPO.FNCFSEJSFDUJFWFΛࢦఆ͍ͯ͠ͳ͍৔߹ʹ੩తղੳͰΤϥʔʹ ͢Δ͜ͱ΋Մೳɻ w ͜ΕʹݶΒͣEJSFDUJWFͷઃఆ๨Ε͸ɺ͢΂ͯ੩తղੳՄೳ w ͦͷଞʹ΋಺෦υϝΠϯʹґଘͨ͠EJSFDUJWFΛ͍͔ͭ͘༻ҙ͍ͯ͠ΔͷͰɺڵຯ͕͋ Δํ͸௚઀ฉ͍͍ͯͩ͘͞ɻ input JoinApplicationInput { applicationID: ID! @id(kind: "Application") @adminApplicationMember adminID: ID! @id(kind: "Admin") }

Slide 66

Slide 66 text

66 EJSFDUJWFͷ׆༻ w ͓͢͢Ίͷ7BMJEBUJPOEJSFDUJWF w )5.-ͷ$POTUSBJOU7BMJEBUJPOจ๏ʹ४ڌͨ͠EJSFDUJWFΛఆٛ w IUUQTEFWFMPQFSNP[JMMBPSHFO64EPDT8FC(VJEF)5.- $POTUSBJOU@WBMJEBUJPO w (SBQI2-ͰεΩʔϚϑΝʔετͳ'PSN7BMJEBUJPO w IUUQTRJJUBDPNTFZBJUFNTEFB w HSBQIRMDPEFHFOUZQFTDSJQUWBMJEBUJPOTDIFNBͰɺϑϩϯτΤϯυͷWBMJEBUJPOΛ ࣗಈੜ੒ w HSBQIRMDPEFHFO͸WBMJEBUJPO༻ͷTDIFNB΋ࣗಈͰੜ੒Ͱ͖Δ ZVQͱ[PE w IUUQT[FOOEFWDPEFIFYBSUJDMFTGFCBBD

Slide 67

Slide 67 text

67 EJSFDUJWFͷ׆༻ w EJSFDUJWFͷ׆༻·ͱΊ w (SBQI2-։ൃʹ͓͍ͯΫϥΠΞϯταΠυͷ%9͕஫໨͞Ε·͕͢ɺόοΫΤϯυͷ %9ʹ͸EJSFDUJWF͕େ͖ͳ໾ׂΛՌ͍ͨͯ͠·͢ɻ w (SBQI2-Λ࢝ΊΔͨΊʹ͸EJSFDUJWF͸ඞਢͰ͸ͳ͍ͨΊݟಀ͞Εͯ͠·͏͜ͱ͕͋Γ ·͕͢ɺ͜ͷΑ͏ʹEJSFDUJWF͸%9Λେ෯ʹվળ͢Δ΋ͷͳͷͰੋඇݕ౼ͯ͠Έͯͩ͘ ͍͞ɻ

Slide 68

Slide 68 text

-JOUFSͷ׆༻

Slide 69

Slide 69 text

69 -JOUFSͷ׆༻ w εΩʔϚۦಈ։ൃͷϝϦοτͱͯ͠ɺεΩʔϚʹରͯ͠੩తղੳπʔϧΛ࣮૷͢Δ͜ͱ ͕Ͱ͖Δ w ࣾ಺ͷಠࣗͷϧʔϧΛ-JOUFSͱ࣮ͯ͠૷͢Δ͜ͱ΋Մೳ w ྫ͑͹QFSNJTTJPOEJSFDUJWFͷ͚ͭ๨ΕͳͲΛݕग़͢Δ͜ͱ΋Մೳ

Slide 70

Slide 70 text

70 -JOUFSͷ׆༻ w FTMJOU w IUUQTHJUIVCDPNBQPMMPHSBQIRMFTMJOUQMVHJOHSBQIRM

Slide 71

Slide 71 text

71 -JOUFSͷ׆༻ w "QQJGZ੡ͷ-JOUFS w HRMHPMBDLJE w IUUQTHJUIVCDPNHRMHPMBDLJE w JEͷࢦఆΛ๨Ε͍ͯΔ2VFSZΛݕग़ w HRMHPOPEFDIFDL w IUUQTHJUIVCDPNHRMHPOPEFDIFDL w /PEFΛ࣮૷͍ͯ͠ͳ͍UZQFΛݕग़ w HRMHPEFQSFDBUFERVFSZ w IUUQTHJUIVCDPNHRMHPEFQSFDBUFERVFSZ w EFQSFDBUFEͳRVFSZΛݕग़ w HRMHPPQUJPOBMTDIFNB w IUUQTHJUIVCDPNHRMHPPQUJPOBMTDIFNB w PQUJPOBMͳ fi FMEΛ4DIFNB͔Βݕग़ w HRMHPRVFSZTUSJOH w IUUQTHJUIVCDPNHRMHPRVFSZTUSJOH w ιʔείʔυͷத͔Β(SBQI2-2VFSZΛநग़

Slide 72

Slide 72 text

72 ίʔυੜ੒πʔϧ w "QQJGZ੡ͷίʔυੜ੒ w :BNBTIPVHRMHFOD w IUUQTHJUIVCDPN:BNBTIPVHRMHFOD w (SBQI2-ΫϥΠΞϯτίʔυͷੜ੒ w "QQJGZͰ͸"1*ςετΛ͢ΔͨΊʹ(Pͷ(SBQI2-ΫϥΠΞϯτΛੜ੒͍ͯ͠·͢ɻ

Slide 73

Slide 73 text

73 ͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠ 4QFBLFS%FDLͷ֓ཁཝʹؔ࿈εϥΠυΛܝࡌ͍ͯ͠·͢