FiNCのWeb API開発事情

fumiyashinozuka 1,868 views 36 slides Feb 03, 2017
Slide 1
Slide 1 of 36
Slide 1
1
Slide 2
2
Slide 3
3
Slide 4
4
Slide 5
5
Slide 6
6
Slide 7
7
Slide 8
8
Slide 9
9
Slide 10
10
Slide 11
11
Slide 12
12
Slide 13
13
Slide 14
14
Slide 15
15
Slide 16
16
Slide 17
17
Slide 18
18
Slide 19
19
Slide 20
20
Slide 21
21
Slide 22
22
Slide 23
23
Slide 24
24
Slide 25
25
Slide 26
26
Slide 27
27
Slide 28
28
Slide 29
29
Slide 30
30
Slide 31
31
Slide 32
32
Slide 33
33
Slide 34
34
Slide 35
35
Slide 36
36

About This Presentation

I explained how FiNC Developer implement APIs.
What gems and what development process we use.
We switched api gems from grape and rabl to ApplicationController and ActiveModelSerializer.
I explained why and its pros/cons.


Slide Content

'J/$w8FC"1*‰CÄ Ø
'J/$*OD4IJOP[VLB'VNJZB

\wC¯p˜T”\q
w3BJMTpw"1*‰CwMO
w3BJMTw"1*‰Ct–˜•”(b(FN
w'J/$pw"1*‰Cwv•

×ü
wðé™û !TIJOPGVNJKQ
w±”̱ Å¤ï´Çž
wå'J/$Öþ p̤ï´Çž
w'J/$žÓæw€\T’‡p›_oV‡`h

FiNC
wÔçµ­žwžÓæ­”³ãC`oM‡b

FiNC = Microservices
w.JDSPTFSWJDFT›>;`oM‡b
IUUQTEFWPUUPEFTDBMJOHXJUINJDSPTFSWJDFTBOEWFSUJDBMEFDPNQPTJUJPO

MicroservicesqMQy
"1*

ÔxAPI‰Cwé›`‡b
d"MMUFBNTXJMMIFODFGPSUIFYQPTFUIFJSEBUBBOE
GVODUJPOBMJUZUISPVHITFSWJDFJOUFSGBDFTd
+F$Ž#F[PT

RailspwAPI‰CrO`oM‡b

API‰Cpx7‘sU|òèq¬R¶UK”
w"1*Ñè”Ü딫
w+40/³æžå ²”
wÅ©áÝïÄ
w嵀
wÞ¿«"1*

FiNCp s8t>;`oMhMO
w"1*Ñè”Ü딫
w(SBQF
w+40/³æžå ²”
wSBCM
wÅ©áÝïÄ\R
w4XBHHFS

w"1*Ñè”Ü딫
w(SBQF"QQMJDBUJPO$POUSPMMFS
w+40/³æžå ²”
wSBCM"DUJWF.PEFM4FSJBMJ[FS
wÅ©áÝïÄ\R
w4XBHHFS+40/4DIFNB QSNEDPNNJUUFF
FiNCpqO>;`oM”MO

w"1*Ñè”Ü딫
w生ï¬Ñ ç›G \`sMp‹Úò$t¤ïÅÙ ïÄ
U {Z”
wIUUQTHJUIVCDPNSVCZHSBQFHSBQF
Grape
module V1
class UsersApi < Grape::API
resource :users do
params do
requires :id, type: Integer
end
get '/:id', rabl: '/v1/users/index' do
@users = User.limit(10)
end
params do
requires :id, type: Integer
optional :name, type: String
end
patch '/:id', rabl: '/v1/users/show' do
@user = User.create(user_params)
end
end
end
end

w+40/³æžå ²”
w ×w%4-pèµÙïµw[UpV”
w JÈsG \UpV”
wIUUQTHJUIVCDPNOFTRVFOBSBCM
rabl
object @user
attributes :id, :name, :created_at, :updated_at
{
"id": 1,
"name": "shinofumijp",
"created_at": "2017-02-02T10:13:52.000+09:00",
"updated_at": "2017-02-02T10:13:52.000+09:00"
}

wÅ©áÝïÄ׈\Rqîæ¥w;™
w"1*[T’׈pÅ©áÝïÄqîæ¥›;™pV”
wIUUQTHJUIVCDPNSVCZHSBQFHSBQFTXBHHFS
Swagger

se ГõQhwT
w(SBQFiq
wIˆÌU OM
w ×w%4-›®Q”žAUK”
wGOpMq\–‹ «ÉµÄUMqV
w³ïÓçt"QQMJDBUJPO$POUSPMMFS›b;b”\qt

se ГõQhwT
w(SBQFSBCMx JÈaWh
w"1*]qtèµÙïµUy’y’tslh
wæ¹”µ¦²›ÇTdhM
w"DUJWF.PEFM4FSJBMJ[FSq+40/4DIFNBpr>

se ГõQhwT
w4XBHHFSp\R^•”Å©áÝïÄpx ØCU“sM
w4b”hŠt8JLJ› {Vb”Uzî÷qm`h
wDPNNJUUFF +40/4DIFNBpr>

²”V 4ƒ

Ôéb\q
w'J/$p–loM”"1*U [
w'J/$pw3BJMT"1*‰CÑé”

ActiveModelSerializer
w+40/³æžå ²”;w(FN
w«åµp¦b”hŠæ¹”µ¦²t²MoM”
wIUUQTHJUIVCDPNSBJMTBQJBDUJWF@NPEFM@TFSJBMJ[FST
# either
class SomeResource < ActiveRecord::Base
# columns: title, body
end
# or
class SomeResource < ActiveModelSerializers ::Model
attributes :title, :body
end
class SomeSerializer < ActiveModel::Serializer
attribute :title, key: :name
attributes :body
end
{
"name": "namevalue",
"body": "bodyvalue"
}

JSON Schema
w+40/›;MoÔ»›G \b”Üwm
wIUUQKTPOTDIFNBPSH
\
UJUMF&YBNQMF4DIFNB
UZQFPCKFDU
QSPQFSUJFT\
pSTU/BNF\
UZQFTUSJOH
^
MBTU/BNF\
UZQFTUSJOH
^
BHF\
EFTDSJQUJPO"HFJOZFBST
UZQFJOUFHFS
NJOJNVN
^
^
SFRVJSFE<pSTU/BNFMBTU/BNF>
^

JSON Schemapî÷qwmUsXs”wxse
wDPNNJUUFF
w+40/4DIFNB›it
w櫤µÄ~èµÙïµw½£¿«
wµÄpèµÙïµw½£¿«
wIUUQTHJUIVCDPNJOUFSBHFOUDPNNJUUFF

JSON Schema {XwŠœrMwpx
wQSNE
w:".-p {Zo+40/qÚ”«¼¢ïÅ©áÝïÄw\RUDó
wIUUQTHJUIVCDPNJOUFSBHFOUQSNE

‡qŠ”q\œsòa
Z/DPNNJUUFFQSNEp+40/4DIFNB›MMòatá;b”SShwú”
IUUQTPUBZDPNCMPHpODBEWFOU

îMwî÷ q
'h ƒ- î÷ 2" ææ”µ

JSON Schema›[
w:".-p[› {Mo+40/qÚ”«¼¢ïÅ©áÝïÄ›\R
w«å žïĤï´Çžt\R`hÅ©áÝïÄ›ž
"$schema": http://json-schema.org/
draft-04/hyper-schema
title: Daily Steps Count
description: Daily Steps Count Resource
stability: prototype
strictProperties: true
type:
- object
definitions:
date:
description: date (JST)
example: "2016-11-01"
type: string
KTPO
NE

((?) JSON Schema + prmd?;tips
wbptá;`oM”pßè«ÄæÏRt„›ð‡d”‹ —
sXsMxc{
w'J/$pxSFTPVSDFTqBQJTtüZoá;`oM”{
wSFTPVSDFTæ¹”µ[›G \{BQJTT’€ °^•”;
wBQJT"1*[›G \{櫤µÄèµÙïµ[pSFTPVSDFT›b;
b”\qp"1* ×w¤ïŸŸU\‡•sM‘Ot`oM”{«Ž
x???{
docs/
!"" schema
#"" meta.yml
#"" schema.json
#"" schema.md
!"" schemata
#"" apis
!"" resources

Controllert??????[
w› b”\qsMlb
class DailyStepsController < ApplicationController
def show
steps = DailyStep.where(user_id: current_user.id)
render json: steps
end
end

w?????x???p[b”
w"DUJWF.PEFM4FSJBMJ[FSx³æžå ¶^•”«åµ›Ibwp
³æžå ¶iwÞÃç›×^b”\q‹K”
w«ó:w"3ÞÃçt‡hU”qV
w«Ã¯è”»w‘OtÞÃ盦Á`hMqV
ActiveModelSerializerpèµÙïµ›[
class DailyStepSerializer < ActiveModel::Serializer
attributes :id, :date, :step
end

µÄpÌæÃ”³ãï¬Ý
wXJMMOFUDPNNJUUFFSBJMT›–Qy34QFDp
BTTFSU@TDIFNB@DPOGPSNU–Q”
wÞ34QFDp+40/4DIFNBqSFTQPOTFCPEZU°•`oM”T›???
pV”
wIUUQTHJUIVCDPNXJMMOFUDPNNJUUFFSBJMT
it 'returns expected response ' do
expect(response.status).to eq 200
json = JSON.parse(response.body)
expect(json['id']).to be_kind_of Integer
expect(json[‘step']).to be_kind_of Integer
end
it 'returns expected response ' do
expect(response.status).to eq 200
assert_schema_conform
end

 æ`hAL
w±”̫堞ïÄpw"1*wÝÝ%*Un’dh
wÅ©áÝïÄ›î÷²tžpV”\qp‰C®pU ÍUlh
wÅ©áÝïÄUÌæÃ”³ãï›`oX•”wpÝïÂ^•”‘O
tslh
wæ¹”µ¦²U`zèµÙïµÜU†`h

’”]J
w׈\R^•hÅ©áÝïÄU¡ˆn’M
w櫤µÄÍåÝ”»wT’«åµw!õ
w¤Ú «é±”ϵtüT•hÅ©áÝïÄwg›mw63-t

OSStuÃ$t¯Û¿Ä
wb;`oM”(FN›–MbXb”hŠt13›ùlh“z(FN›
^loM‡b
wIUUQTHJUIVCDPNJOUFSBHFOUQSNEQVMM

™r>`hM\q
w"1*«å žïÄw׈\R
wIUUQTHJUIVCDPNJOUFSBHFOUIFSPJDTqT
wÌ”´ãÇï¬0
w¤å”èµÙïµwžè=
wIUUQTUPPMTJFUGPSHIUNMSGD›€ßt

;
w'J/$žÓ曑–`XS&M`‡b‚
w Ÿ4¯”ÅTIJOPpODKQpž§¢ïÄJåpV‡b

K“UqO]_M‡`h‚
'J/$px±”̱ Å¤ï´Çž›7 B`oM‡b