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

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. ΧϥʔϛʔϦϐʔτͷߏ੒ "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 ॳճΞΫηε࣌
  2. "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" } } ϦΫΤετ Ϩεϙϯε
  3. 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
  4. 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
  5. 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:".- ʹॻ͘
  6. 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: # ...
  7. 0QFO"1*υΩϡϝϯτͷ࡞੒ w3BJMTϓϩδΣΫτ಺ʹ0QFO"1*υΩϡϝϯτ഑ஔ . !"" app !"" bin !"" db !""

    doc # ഑ԼʹϦιʔε/ΤϯυϙΠϯτ͝ͱʹ֨ೲ !"" lib !"" public !"" spec #"" ... doc #"" spec #"" v1 !"" definitions # Ϧιʔεఆٛ $ !"" shipment.yml $ #"" ... !"" index.yml # Ϧιʔε/ΤϯυϙΠϯτ·ͱΊ༻ #"" paths # ΤϯυϙΠϯτఆٛ !"" admin $ !"" users.yml $ !"" ...
  8. 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
  9. ϨεϙϯεόϦσʔγϣϯͷ࣮ߦྫ # 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
  10. ϨεϙϯεόϦσʔγϣϯͷ࣮ߦྫ # 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*υΩϡϝϯτͱ࣮ϨεϙϯεͷҰகΛνΣοΫͰ͖Δ
  11. 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
  12. # 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