$30 off During Our Annual Pro Sale. View Details »

GMOペパボの Rails & Vue.js プロダクト開発の現場 / Rails Developers Meetup 2017

kymmtchan
December 09, 2017

GMOペパボの Rails & Vue.js プロダクト開発の現場 / Rails Developers Meetup 2017

Rails Developers Meetup 2017での発表資料です。ペパボにおける新規プロダクト開発の流れと、スキーマファースト開発を紹介しています。

kymmtchan

December 09, 2017
Tweet

Other Decks in Technology

Transcript

  1. !LFODIBOGFBU!LZNNU(.01FQBCP *OD
    3BJMT%FWFMPQFST.FFUVQ
    (.0ϖύϘͷ3BJMT7VFKT
    ϓϩμΫτ։ൃͷݱ৔

    View Slide

  2. νʔϑςΫχΧϧϦʔυ
    &$ࣄۀ෦
    ∁ڮ݈Ұ!LFODIBO
    ΤϯδχΞ
    &$ࣄۀ෦ΧϥʔϛʔϦϐʔτνʔϜ
    ࢁຊߒฏ!LZNNU

    View Slide

  3. View Slide

  4. ܅΋ϖύϘͰಇ͔ͳ͍͔ʁ
    ࠷৽ͷ࠾༻৘ใΛνΣοΫˠ !QC@SFDSVJU

    View Slide

  5. ໨࣍
    wαʔϏεͷ֓ཁͱΞʔΩςΫνϟ
    wϓϩδΣΫτͷ্ཱͪ͛ͱ೔ʑͷ։ൃ
    wεΩʔϚϑΝʔετ։ൃͷݱ৔

    View Slide

  6. ໨࣍
    wαʔϏεͷ֓ཁͱΞʔΩςΫνϟ
    wϓϩδΣΫτͷ্ཱͪ͛ͱ೔ʑͷ։ൃ
    wεΩʔϚϑΝʔετ։ൃͷݱ৔

    View Slide

  7. IUUQTDPMPSNFSFQFBUKQ

    View Slide

  8. wఆظൢചʹಛԽͨ͠&$αʔϏε
    wϓϩμΫτΦʔφʔɺσΟϨΫλɺσβΠφɺ

    ΤϯδχΞ͕νʔϜʹͳͬͯ։ൃ
    w3VCZPO3BJMT7VFKTΛ)FSPLVͰӡ༻

    View Slide

  9. શମײ
    "EEPO
    ΦϒδΣΫτ
    ετϨʔδ
    ߦಈϩάू໿ɾ෼ੳ
    $%/ ։ൃɾίϛϡχέʔγϣϯ

    πʔϧ
    Ϣʔβʔ ։ൃνʔϜ

    View Slide

  10. ։ൃνʔϜ
    ϓϩμΫτ
    Φʔφʔ
    σΟϨΫλ ࣄۀ෦෦௕
    10νʔϜ
    ΤϯδχΞ
    σβΠφ
    2"νʔϜ
    σβΠϯઓུ
    νʔϜ
    Πϯϑϥ
    άϧʔϓ

    View Slide

  11. ໨࣍
    wαʔϏεͷ֓ཁͱΞʔΩςΫνϟ
    wϓϩδΣΫτͷ্ཱͪ͛ͱ೔ʑͷ։ൃ
    wεΩʔϚϑΝʔετ։ൃͷݱ৔

    View Slide

  12. ϓϩδΣΫτͷ্ཱͪ͛
    wΠϯηϓγϣϯσοΩ
    wυϥοΧʔ෩ΤΫααΠζ
    wྨࣅαʔϏεͷϞσϦϯά
    wౡࠜ߹॓

    View Slide

  13. ΠϯηϓγϣϯσοΩ
    wʮΞδϟΠϧαϜϥΠʯͰ঺հ͞Ε͍ͯΔϓϩδΣΫ
    τͷ্ཱͪ͛࣌ʹ༗ޮͳϓϥΫςΟεͰ͋Δ
    wݸͷ࣭໰ʹνʔϜͰ౴͑Λग़͢͜ͱͰɺϓϩδΣ
    ΫτɾϓϩμΫτͷํ޲ੑΛ߹ҙ͢Δ
    wࠓճ͸൒೔º̎೔Ͱݸͷ࣭໰ʹ௅ઓͨ͠

    View Slide

  14. ΦϑΟεͷҰ֯Λઐ༻εϖʔεʹͯࣾ͠಺߹॓

    View Slide

  15. υϥοΧʔ෩ΤΫααΠζ
    wΠϯηϓγϣϯσοΩಉ༷ʮΞδϟΠϧαϜϥΠʯͰ
    ঺հ͞Ε͍ͯΔνʔϜϏϧσΟϯάͷϓϥΫςΟε
    wͭͷ࣭໰ʹ౴͑Δ͜ͱͰɺ͓ޓ͍ͷಘҙ෼໺΍Ձ஋
    ؍Λڞ༗͠ɺϝϯόʔͷ૬ޓཧղʹޮՌ͕͋Δ
    wৄ͘͠͸ϖύϘςοΫϒϩάΛࢀর
    wIUUQTUFDIQFQBCPDPNUIFESVDLFSFYFSDJTF

    View Slide

  16. ྨࣅαʔϏεͷϞσϦϯά
    ։ൃʹೖΔલʹɺྨࣅͷαʔϏε
    Λ࢖ͬͯΈͯɺ಺෦ߏ଄Λ૝૾Ͱ
    ϞσϦϯάͯ͠ΈΔɻ
    ࣄۀυϝΠϯͷޠኮΛऩूͨ͠Γɺ
    Ϟσϧؒͷؔ࿈Λ࡞ΔલʹΠϝʔ
    δͰ͖Δɻ

    View Slide

  17. দߐ߹॓
    3VCZͷ੟஍ɺদߐͰ։ൃ
    ߹॓Λ࣮ࢪɻ

    View Slide

  18. ೔ʑͷ։ൃ
    wिؒεϓϦϯτͷεΫϥϜ։ൃ
    wϢʔβςετ
    w Նͷ
    ࣗ༝ݚڀ

    View Slide

  19. िؒεϓϦϯτͷεΫϥϜ ͬΆ͍
    ։ൃ
    w໦༵࢝·ΓͷिؒεϓϦϯτ
    wਫ༵༦ํʮ;Γ͔͑Γ ,15"
    ʯͱʮϓϥϯχϯάʯ
    wʮ;Γ͔͑ΓʯͷલʹσϞλΠϜ
    wՐ༵༦ํʹʮόοΫϩάϦϑΝΠϯϝϯτʯ
    wλεΫ؅ཧ͸1JWPUBM5SBDLFS෺ཧΧϯόϯ

    View Slide

  20. Ϣʔβςετ
    wϦϦʔεલ͸ࣾ಺ͷϝϯόʔʹɺϦϦʔεޙ͸ࣾ֎ͷ
    λʔήοτϢʔβʹΞϓϦέʔγϣϯΛ৮ͬͯ΋Β͍
    ϑΟʔυόοΫΛಘΔ
    wૢ࡞ΛಈըʢϦΞϧλΠϜPS࿥ը
    Ͱݟͳ͕ΒɺϢʔ
    βͷൃݴͱؾ͕͍ͭͨ఺Λॻ͖ग़͠Ϛοϐϯά͢Δ
    w5IBOLTσβΠϯઓུνʔϜ

    View Slide

  21. ࿥ը΍தܧΛΈͳ͕Β

    ؾʹͳͬͨͱ͜ΖΛॻ͖ग़͢
    தܧ͸(PPHMF)BOHPVUͷը໘ڞ༗ϚΠΫ

    View Slide

  22. Ϛοϐϯάͨ͠΋ͷ͔Βಉ͡΋ͷΛચ͍ग़͠
    ༏ઌॱҐΛ෇͚ͯܭըʹམͱ͠ࠐΉ

    View Slide

  23. Նͷ
    ࣗ༝ݚڀ
    ٕज़తͳෆ҆ཁૉ΍νϟ
    Ϩϯδ͍ͨ͠τϐοΫΛ
    ࣗ༝ʹݚڀ͠ɺͦͷ݁Ռ
    ΛJTTVFͰڞ༗͢Δ

    View Slide

  24. ໨࣍
    wαʔϏεͷ֓ཁͱΞʔΩςΫνϟ
    wϓϩδΣΫτͷ্ཱͪ͛ͱ೔ʑͷ։ൃ
    wεΩʔϚϑΝʔετ։ൃͷݱ৔

    View Slide

  25. ΧϥʔϛʔϦϐʔτͷߏ੒
    "1*αʔόʔ
    ϑϩϯτΤϯυαʔόʔ
    ΫϥΠΞϯτ
    ॳճΞΫηε࣌
    +40/Λฦ͢8FC"1*
    +40/Λฦ͢8FC"1*
    ϒϥ΢β্Ͱ41"͕ಈ࡞

    View Slide

  26. ΧϥʔϛʔϦϐʔτͷߏ੒
    "1*αʔόʔ
    ϑϩϯτΤϯυαʔόʔ
    ΫϥΠΞϯτ
    ॳճΞΫηε࣌
    +40/Λฦ͢8FC"1*
    +40/Λฦ͢8FC"1*
    ϒϥ΢β্Ͱ41"͕ಈ࡞

    View Slide

  27. ΧϥʔϛʔϦϐʔτͷߏ੒
    "1*αʔόʔ
    ϑϩϯτΤϯυαʔόʔ
    ΫϥΠΞϯτ
    +40/Λฦ͢8FC"1*
    +40/Λฦ͢8FC"1*
    ϒϥ΢β্Ͱ41"͕ಈ࡞
    w ॳظදࣔΛߴ଎ʹ͍ͨ͠Ұ෦ϖʔδͰ4FSWFS4JEF3FOEFSJOH 443

    w ҎԼʮ৽نϓϩδΣΫτ΁ͷ7VFKTY41"Y443ͷಋೖʯ͕ৄ͍͠

    https://www.slideshare.net/TsuchiKazu/vuejs-x-spa-x-ssr-79213417
    ॳճΞΫηε࣌

    View Slide

  28. ॳճΞΫηε࣌
    ΧϥʔϛʔϦϐʔτͷߏ੒
    "1*αʔόʔ
    ϑϩϯτΤϯυαʔόʔ
    ΫϥΠΞϯτ
    +40/Λฦ͢8FC"1*
    +40/Λฦ͢8FC"1*
    ϒϥ΢β্Ͱ41"͕ಈ࡞
    w3BJMT"1*ϞʔυΛ༻͍ͨ8FC"1*
    w41"͔Βར༻͢Δ͜ͱΛ૝ఆͨ͠"1*
    w4JEFLJRͱTJEFLJRTDIFEVMFSͰඇಉظॲཧͱఆظόον࣮ߦ

    View Slide

  29. ΧϥʔϛʔϦϐʔτͷߏ੒
    "1*αʔόʔ
    ϑϩϯτΤϯυαʔόʔ
    ΫϥΠΞϯτ
    +40/Λฦ͢8FC"1*
    +40/Λฦ͢8FC"1*
    ϒϥ΢β্Ͱ41"͕ಈ࡞
    ॳճΞΫηε࣌

    View Slide

  30. ΧϥʔϛʔϦϐʔτͷ։ൃϑϩʔ
    APIఆٛ
    νʔϜ
    ϨϏϡʔ
    ։ൃͱ
    ςετ
    ݁߹

    View Slide

  31. ΧϥʔϛʔϦϐʔτͷ։ൃϑϩʔ
    APIఆٛ
    νʔϜ
    ϨϏϡʔ
    ։ൃͱ
    ςετ
    ݁߹
    ˡى఺͸ίί

    View Slide

  32. "1*ఆٛΛ׆༻ͨ͠։ൃ
    w"1*ఆٛΛ༻͍ͨϑϩϯτΤϯυͱόοΫΤϯυฒߦ
    ։ൃ
    wεΩʔϚϑΝʔετ։ൃ
    w4QFDJpDBUJPO'JSTU%FWFMPQNFOU

    SFGεΩʔϚϑΝʔετ։ൃͷεεϝPOLOJOKB

    https://blog.onk.ninja/2017/09/21/schema_first_development

    View Slide

  33. "1*ఆٛͱ͸
    w8FC"1*ʢҎ߱"1*ͱ͢Δʣͷ࢓༷ΛطఆͷܗࣜͰॻ͘͜ͱ
    wΤϯυϙΠϯτɺϦΫΤετɺεςʔλείʔυɺϨεϙϯε
    PUT /shipments/:id
    path: id
    body: {
    "shipment": {
    "status": "active",
    "delivery_on": "2017-12-09"
    }
    }
    status: 200, 404, 422
    body: {
    "shipment": {
    "status": "active",
    "delivery_on": "2017-12-09",
    "created_at": "2017-12-09T00:00:00",
    "updated_at": "2017-12-09T00:00:00"
    }
    }
    ϦΫΤετ Ϩεϙϯε

    View Slide

  34. "1*ఆٛΛ׆༻ͨ͠։ൃͷϝϦοτ
    w։ൃϝϯόʔؒͰϦΫΤετ΍Ϩεϙϯεͷܗࣜʹ

    ର͢ΔೝࣝͷζϨ͕ݮΔ
    w"1*ఆٛࣗମΛύʔεͯ͠ɺ͍Ζ͍Ζ׆༻Ͱ͖Δ
    wΤίγεςϜ͕ӫ͍͑ͯΔͱศར
    wεϜʔζͳϑϩϯτΤϯυͱόοΫΤϯυฒߦ։ൃ

    View Slide

  35. 0QFO"1*
    wΧϥʔϛʔϦϐʔτͷ"1*ఆٛͷܗࣜͱͯ͠0QFO"1*ΛબΜͩ
    w0QFO"1*ͱ͸
    w"1*ఆٛΛॻͨ͘Ίͷ਺͋Δܗࣜͷͻͱͭ
    wଞʹ͸"1*#MVFQSJOU΍3".-ͳͲ
    w+40/͔:".-Ͱॻ͘
    w೥ݱࡏɺ"1*࢓༷هड़ϑΥʔϚοτͷओྲྀͱͳ͍ͬͯΔ

    SFG.VMF4PGU+PJOTUIF0QFO"1**OJUJBUJWF5IF&OEPGUIF"1*4QFD8BST

    https://swagger.io/blog/mulesoft-joins-the-openapi-initiative/

    View Slide

  36. 0QFO"1*υΩϡϝϯτͷྫ
    # definitions/shipment.yml
    definitions:
    Shipment:
    type: object
    properties:
    id:
    type: integer
    example: 1
    status:
    type: string
    enum:
    - unshipped
    - shipped
    - canceled
    # paths/shipment.yml
    paths:
    /shipments/{shipmentId}:
    get:
    parameters:
    - shipmentId:
    in: path
    name: shipmentId
    type: integer
    required: true
    responses:
    '200':
    schema:
    type: object
    properties:
    shipment:
    $ref: '#/definitions/Shipment'
    ˡΤϯυϙΠϯτఆٛ
    ˣϦιʔεఆٛ ΄΅+40/4DIFNB

    View Slide

  37. 0QFO"1*υΩϡϝϯτͷྫ
    # definitions/shipment.yml
    definitions:
    Shipment:
    type: object
    properties:
    id:
    type: integer
    example: 1
    status:
    type: string
    enum:
    - unshipped
    - shipped
    - canceled
    # paths/shipment.yml
    paths:
    /shipments/{shipmentId}:
    get:
    parameters:
    - shipmentId:
    in: path
    name: shipmentId
    type: integer
    required: true
    responses:
    '200':
    schema:
    type: object
    properties:
    shipment:
    $ref: '#/definitions/Shipment'
    ˡΤϯυϙΠϯτఆٛ
    ˣϦιʔεఆٛ ΄΅+40/4DIFNB

    View Slide

  38. 0QFO"1*υΩϡϝϯτͷྫ
    # definitions/shipment.yml
    definitions:
    Shipment:
    type: object
    properties:
    id:
    type: integer
    example: 1
    status:
    type: string
    enum:
    - unshipped
    - shipped
    - canceled
    # paths/shipment.yml
    paths:
    /shipments/{shipmentId}:
    get:
    parameters:
    - shipmentId:
    in: path
    name: shipmentId
    type: integer
    required: true
    responses:
    '200':
    schema:
    type: object
    properties:
    shipment:
    $ref: '#/definitions/Shipment'
    ˡΤϯυϙΠϯτఆٛ
    ˣϦιʔεఆٛ ΄΅+40/4DIFNB

    ͜ΕΛຕͷ+40/ PS:".-
    ʹॻ͘

    View Slide

  39. 0QFO"1*ͱ4XBHHFS
    w0QFO"1*JTGPSNFSMZLOPXOBT4XBHHFS
    w4NBSUCFBSࣾ։ൃͷ4XBHHFSΛ(PPHMF΍.JDSPTPGU
    ໊͕Λ࿈ͶΔ0QFO"1**OJUJBUJWFʹҠ؅
    w4XBHHFS0QFO"1*
    w͜ͷ໊࢒Ͱ0QFO"1*༻ͷπʔϧ͸4XBHHFSdͱ

    ͍͏໊લ

    View Slide

  40. 0QFO"1*υΩϡϝϯτͷ࡞੒
    wϦιʔεఆٛΤϯυϙΠϯτఆٛ͝ͱʹ:".-

    ϑΝΠϧΛ෼͚Δ
    # paths/user.yml
    paths:
    /admin/users
    # ...
    # index.yml
    swagger: '2.0'
    # ...
    paths:
    /users:
    $import: ./paths/users.yml
    definitions:
    Shipment:
    $import: ./definitions/shipment.yml
    # definitions/shipment.yml
    definitinos:
    Shipment:
    # ...

    View Slide

  41. 0QFO"1*υΩϡϝϯτͷ࡞੒
    w3BJMTϓϩδΣΫτ಺ʹ0QFO"1*υΩϡϝϯτ഑ஔ
    .
    !"" app
    !"" bin
    !"" db
    !"" doc # ഑ԼʹϦιʔε/ΤϯυϙΠϯτ͝ͱʹ֨ೲ
    !"" lib
    !"" public
    !"" spec
    #"" ...
    doc
    #"" spec
    #"" v1
    !"" definitions # Ϧιʔεఆٛ
    $ !"" shipment.yml
    $ #"" ...
    !"" index.yml # Ϧιʔε/ΤϯυϙΠϯτ·ͱΊ༻
    #"" paths # ΤϯυϙΠϯτఆٛ
    !"" admin
    $ !"" users.yml
    $ !"" ...

    View Slide

  42. 0QFO"1*υΩϡϝϯτͷ࡞੒
    w:BNM3FG3FTPMWFSΛ࢖ͬͯϚʔδͯ͠ຕͷ+40/
    TXBHHFSKTPO
    Խ

    https://github.com/Joe-noh/yaml_ref_resolver
    # swagger_json_generator.rb
    require 'yaml_ref_resolver'
    resolver = YamlRefResolver.new(key: '$import')
    json = resolver.resolve!('./index.yml')
    File.open('./public/swagger.json', 'w') { |f| f.write(json) }
    # index.yml
    swagger: '2.0'
    # ...
    paths:
    /admin/users:
    $import: ./paths/admin/users.yml
    definitions:
    Shipment:
    $import: ./definitions/shipment.yml

    View Slide

  43. 4XBHHFS&EJUPSΛิॿతʹ࢖ͬͯ
    TZOUBYFSSPSΛආ͚Δ

    View Slide

  44. View Slide

  45. ΧϥʔϛʔϦϐʔτͷ։ൃϑϩʔ
    APIఆٛ
    νʔϜ
    ϨϏϡʔ
    ։ൃͱ
    ςετ
    ݁߹

    View Slide

  46. "1*ఆٛͱνʔϜϨϏϡʔ
    w:".-ͰΤϯυϙΠϯτఆٛͱؔ࿈͢ΔϦιʔεఆٛ
    Λॻ͘
    wνʔϜϝϯόʔ͸୭Ͱ΋ॻ͘

    View Slide

  47. "1*ఆٛͱνʔϜϨϏϡʔ
    w"1*ఆٛΛॻ͍ͯ1VMM3FRVFTUΛ࡞ͬͨΒνʔϜͰϨϏϡʔ͢Δ
    w໋໊ɺϦιʔεͷ಺༰ɺύϥϝʔλɺϨεϙϯεͳͲΛݟΔ
    w0,ͳΒ"1*ఆ͚ٛͩϚʔδʂ

    View Slide

  48. ΧϥʔϛʔϦϐʔτͷ։ൃϑϩʔ
    APIఆٛ
    νʔϜ
    ϨϏϡʔ
    ։ൃͱ
    ςετ
    ݁߹

    View Slide

  49. "1*ఆٛͱ։ൃ
    wϑϩϯτΤϯυ
    w4XBHHFS$PEFHFOͰ0QFO"1*υΩϡϝϯτ͔Β

    ελϒαʔόΛੜ੒͢Δ

    0QFO"1*ͷϨεϙϯεྫఆٛΛ΋ͱʹ4XBHHFS$PEFHFOͰελϒαʔόΛੜ੒͢Δ

    https://qiita.com/kymmt90/items/6a254669cd6c7f2b3cf
    w"1*ͷ࣮૷Λ଴ͨͣʹฒߦ։ൃͰ͖Δ

    View Slide

  50. "1*ఆٛͱ։ൃ
    wόοΫΤϯυ
    w0QFO"1*υΩϡϝϯτͱͷ੔߹ੑΛऔΓͳ͕Β࣮૷
    ͢Δඞཁ͕͋Δ

    View Slide

  51. "1*ఆٛͱ࣮"1*ͷ੔߹ੑ
    w0QFO"1*υΩϡϝϯτ্ͷ"1*ఆٛͱ࣮"1*ͷڍಈͷ
    ੔߹ੑΛͱΓɺϨεϙϯεͷܗࣜͷζϨΛආ͚Δ
    wϑϩϯτΤϯυ͸0QFO"1*υΩϡϝϯτΛਖ਼ͱͯ͠
    ฒߦ։ൃ͍ͯ͠ΔͨΊ
    w"1*ఆٛͱ࣮ϨεϙϯεΛࣗಈͰಥ߹Ͱ͖Δͱศར

    View Slide

  52. ࣗಈͰ੔߹ੑΛνΣοΫ
    w34QFDͷ3FRVFTU4QFD࣮ߦ࣌ͷϨεϙϯε+40/ͱ0QFO"1*ʹ

    ॻ͍ͨϨεϙϯεͷ+40/4DIFNBͷ੔߹ੑΛνΣοΫ͍ͨ͠
    wࣗಈͰϨεϙϯεΛόϦσʔγϣϯ͢ΔHFNΛ࡞ͬͯಋೖͨ͠

    4DIFNB$POGPSNJTUhttps://github.com/kymmt90/schema_conformist
    w$PNNJUUFF3BJMTͷassert_schema_conformϝιουΛར༻

    https://github.com/willnet/committee-rails
    wνΣοΫ͠๨ΕΛͳ͘͢

    View Slide

  53. ϨεϙϯεόϦσʔγϣϯͷ࣮ߦྫ
    # public/swagger.json
    # GET /users/:id͸ҎԼͷJSONΛฦ͢ͱ͍͏࢓༷
    definitinos:
    User:
    type: object
    properties:
    email:
    type: string
    status:
    type: string
    enum:
    - active
    - suspended
    # ...
    # spec/requests/users_spec.rb
    # Θ͟ͱemailΛؚΊͳ͍࣮૷ʹରͯ͠Request SpecΛ࣮ߦ
    RSpec.describe 'Users', type: :request do
    describe 'GET /users/:id' do
    it 'returns a valid response' do
    get "/users/#{user.id}" # ...
    end
    end
    end

    View Slide

  54. ϨεϙϯεόϦσʔγϣϯͷ࣮ߦྫ
    # OpenAPIυΩϡϝϯτதͷJSON Schemaͱ࣮ϨεϙϯεͷJSON͕ζϨͨͱ͖ʢemailΛ࣮ϨεϙϯεʹؚΊΒΕ͍ͯͳ͍ͱ͖ʣ
    1) Users GET /users/:id
    Failure/Error: assert_schema_conform
    Committee::InvalidResponse:
    Invalid response.
    #: failed schema #/properties//users/{userId}/properties/GET: "email" wasn't supplied.
    HFNΛೖΕ͓͚ͯͩ͘Ͱ3FRVFTU4QFDͷ࣮ߦ࣌ʹࣗಈͰ

    0QFO"1*υΩϡϝϯτͱ࣮ϨεϙϯεͷҰகΛνΣοΫͰ͖Δ

    View Slide

  55. ੔߹ੑνΣοΫͷ͘͠Έ
    wϨεϙϯεΛ"1*ఆٛதͷ+40/4DIFNBͰ

    όϦσʔγϣϯ͢ΔͨΊʹɺ$PNNJUUFF3BJMTͷ
    assert_schema_conformΛͲ͔͜Ͱ࣮ߦ͢Δ
    wͲ͕͍͍͔͜ʁ

    View Slide

  56. module ActionDispatch
    module Integration #:nodoc:
    module RequestHelpers
    def get(path, **args)
    process(:get, path, **args)
    end
    # ...
    end
    class Session
    include TestProcess, RequestHelpers, Assertions
    def process(method, path, params: nil, headers: nil, env: nil, xhr: false, as: nil)
    # ...
    3FRVFTU4QFDͷ)551ϦΫΤετൃߦϝιουʢget postͳͲʣͷ

    ࣮ମͰ͋ΔActionDispatch::Integration::Session#process

    View Slide

  57. # lib/schema_conformist/
    process_with_assertion.rb
    module SchemaConformist
    module ProcessWithAssertion
    # ...
    def process(*args)
    super *args
    # ...
    assert_schema_conform
    end
    end
    end
    )551Ϩεϙϯεऔಘ௚ޙʹassert_schema_conformΛ

    ࣮ߦ͢ΔϝιουΛ࣋ͭϞδϡʔϧΛprependͯ͠ಈ࡞Λॻ͖׵͑✌
    # lib/action_dispatch/integration.rb
    module ActionDispatch
    module Integration
    class Session
    prepend SchemaConformist::ProcessWithAssertion
    end
    end
    end

    View Slide

  58. ΧϥʔϛʔϦϐʔτͷ։ൃϑϩʔ
    APIఆٛ
    νʔϜ
    ϨϏϡʔ
    ։ൃͱ
    ςετ
    ݁߹

    View Slide

  59. "1*ఆٛͱ݁߹
    w͋Δ"1*ʹ͍ͭͯϑϩϯτΤϯυͱόοΫΤϯυͷฒߦ։ൃ͕׬ྃ͢
    Δͨͼʹ݁߹
    wपͰͻͱͭͷΤϯυϙΠϯτʹ͍ͭͯͷػೳ͕Ͱ͖Δ
    w࠷ऴతʹɺݸͷΤϯυϙΠϯτΛ࣋ͭ"1*ͱɺͦΕΛར༻ͨ͠41"
    ͔ΒͳΔ8FCΞϓϦέʔγϣϯΛɺΤϯδχΞਓº͔݄ڧͰ։ൃ
    Ͱ͖ͨ

    View Slide

  60. ·ͱΊ

    View Slide

  61. ໨࣍
    wαʔϏεͷ֓ཁͱΞʔΩςΫνϟ
    wϓϩδΣΫτͷΩοΫΦϑͱ೔ʑͷ։ൃϓϩηε
    wΧϥʔϛʔϦϐʔτʹ͓͚ΔεΩʔϚϑΝʔετ։ൃ

    View Slide

  62. ·ͱΊ
    wϓϩμΫτΛνʔϜͰ։ൃ͍ͯͨ͘͠Ίͷ

    ϓϥΫςΟεΛ঺հ͠·ͨ͠
    w3BJMT7VFKTͳ৽ن&$ϓϩμΫτͷ։ൃͰ

    εΩʔϚϑΝʔετ։ൃͨ͠ࣄྫΛ঺հ͠·ͨ͠
    w࠙਌ձͳͲͰ͓࿩͠͠·͠ΐ͏

    View Slide