Share
Embed
GMOペパボの Rails & Vue.js プロダクト開発の現場 / Rails Developers Meetup 2017
Rails Developers Meetup 2017での発表資料です。ペパボにおける新規プロダクト開発の流れと、スキーマファースト開発を紹介しています。
kymmtchan
December 09, 2017
Transcript
62 slides
-
ΧϥʔϛʔϦϐʔτͷߏ "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 ॳճΞΫηε࣌ -
ॳճΞΫηε࣌ ΧϥʔϛʔϦϐʔτͷߏ "1*αʔόʔ ϑϩϯτΤϯυαʔόʔ ΫϥΠΞϯτ +40/Λฦ͢8FC"1* +40/Λฦ͢8FC"1* ϒϥβ্Ͱ41"͕ಈ࡞ w3BJMT"1*ϞʔυΛ༻͍ͨ8FC"1* w41"͔Βར༻͢Δ͜ͱΛఆͨ͠"1*
w4JEFLJRͱTJEFLJRTDIFEVMFSͰඇಉظॲཧͱఆظόον࣮ߦ -
"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" } } ϦΫΤετ Ϩεϙϯε -
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 -
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 -
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:".- ʹॻ͘ -
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: # ... -
0QFO"1*υΩϡϝϯτͷ࡞ w3BJMTϓϩδΣΫτʹ0QFO"1*υΩϡϝϯτஔ . !"" app !"" bin !"" db !""
doc # ԼʹϦιʔε/ΤϯυϙΠϯτ͝ͱʹ֨ೲ !"" lib !"" public !"" spec #"" ... doc #"" spec #"" v1 !"" definitions # Ϧιʔεఆٛ $ !"" shipment.yml $ #"" ... !"" index.yml # Ϧιʔε/ΤϯυϙΠϯτ·ͱΊ༻ #"" paths # ΤϯυϙΠϯτఆٛ !"" admin $ !"" users.yml $ !"" ... -
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 -
ϨεϙϯεόϦσʔγϣϯͷ࣮ߦྫ # 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 -
ϨεϙϯεόϦσʔγϣϯͷ࣮ߦྫ # 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*υΩϡϝϯτͱ࣮ϨεϙϯεͷҰகΛνΣοΫͰ͖Δ -
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 -
# 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