Slide 1

Slide 1 text

Daisuke Aritomo (@osyoyu) / Kaigi on Rails 2022 ྡͷ API ͷσʔλΛ Rails Β͘͠ɺ͠ͳ΍͔ʹѻ͏

Slide 2

Slide 2 text

@osyoyu Ͱ͢ • ΫοΫύουͰຖ೔ Rails Λॻ͍ͯ·͢ • ී௨ͷ Ruby ͕޷͖ • ISUCON Ͱ Ruby Λ༏উ͍ͤͨ͞

Slide 3

Slide 3 text

ྡͷ API ͷσʔλΛ Rails Β͘͠ɺ͠ͳ΍͔ʹѻ͏

Slide 4

Slide 4 text

API ΞΫηεͳ͠Ͱ͸αʔϏεΛ࡞Εͣ ୭΋͕ API αʔόʔͱΫϥΠΞϯτͷ྆ํΛ࡞Δ େ API ࣌୅

Slide 5

Slide 5 text

API αʔόʔΛ࡞Δͱ͖͸ ϓϥΫςΟεཱ͕֬͞Ε͍ͯΔ

Slide 6

Slide 6 text

ҰํɺΫϥΠΞϯτΛ࡞Δͱ͖͸

Slide 7

Slide 7 text

ҰํɺΫϥΠΞϯτΛ࡞Δͱ͖͸

Slide 8

Slide 8 text

ҰํɺΫϥΠΞϯτΛ࡞Δͱ͖͸ API ΫϥΠΞϯτͷ࡞Γํ͸ 
 ඞͣ͠΋੔ཧ͞Ε͍ͯͳ͍

Slide 9

Slide 9 text

ྡͷ API ͷσʔλΛ Rails Β͘͠ɺ͠ͳ΍͔ʹѻ͏ ͍͍ײ͡ͷ API ΫϥΠΞϯτͷ࡞Γ͔ͨ

Slide 10

Slide 10 text

ʮ͍͍ײ͡ͷ API ΫϥΠΞϯτͷ࡞Γํʯ ΫοΫύουͰ͋Γ͕ͪͳ୊ࡐΛྫʹ 
 έʔεελσΟͯ͠ΈΑ͏

Slide 11

Slide 11 text

ͲͷΑ͏ͳ Ruby ΠϯλʔϑΣʔεʹ͢Δ͔ʁ Ϩγϐίϯςετͷ microservice ͷྫ User (MySQL) Recipe 
 Contest (MySQL) Recipe (API) Recipe 
 ContestEntry (MySQL) N 1 N 1 N 1 1 1

Slide 12

Slide 12 text

• ҟͳΔιʔεछผͷ en ti ty ͸ 
 ҟͳΔऔಘํࣜΛఏڙ͢Δ • MySQL ༝དྷ͸ AR::Base Λ 
 ܧঝ͢ΔΫϥεͰදݱ • ֎෦༝དྷ͸ผͷΫϥεͰදݱ 
 (i.e. AR::Base Λܧঝ͠ͳ͍) (1) ιʔεͷछผʹண໨͢Δ User (MySQL) Recipe 
 Contest (MySQL) Recipe (API) Recipe 
 ContestEntry (MySQL) N 1 N 1 N 1 1 1

Slide 13

Slide 13 text

No content

Slide 14

Slide 14 text

has_one ͸ૉ௚ʹදݱͰ͖ͦ͏

Slide 15

Slide 15 text

belongs_to Ͱ N+1 ʹͳΓ͕ͪ has_one ͸ૉ௚ʹදݱͰ͖ͦ͏ has_manyͱ belongs_toͷෳ߹

Slide 16

Slide 16 text

(1) ιʔεͷछผʹண໨͢Δ ੑ࣭͕ҟͳΔ (DB/API) σʔλ͕֤ʑʹదͨ͠ߏ଄Λ΋ͭ ϓϩάϥϜͷڍಈΛ૝૾͠΍͍͢ 👍 JOIN ΍ ؔ࿈ (associa ti on) Λදݱ͢Δͷʹແཧ͕ੜ͡Δ 🤔

Slide 17

Slide 17 text

• ಉҰͷυϝΠϯͷ en ti ty ͸ 
 ಉҰͷऔಘํ๏Λఏڙ͢Δ • ΞϓϦͷυϝΠϯ্ͳΒ͹ 
 ͢΂ͯ Ac ti veRecord-like ͳ 
 औಘํࣜΛఏڙ͢Δ (2) υϝΠϯڥքʹண໨͢Δ Tweet (API) User (MySQL) Recipe 
 Contest (MySQL) Recipe (API) Recipe 
 ContestEntry (MySQL) 1 N 1 N 1 1

Slide 18

Slide 18 text

ਓྨͷྺ࢙: ActiveResource, Her, ... • Ac ti veResource • RESTful API Λ͍͍ײ͡ʹ model ͬΆͯ͘͘͠ΕΔ • Rails 3.2 ·Ͱͷඪ४ػೳͩͬͨ • Her • ͜Ε΋ಉ͡Α͏ͳ໨తͷ Gem • ΄͔ʹ΋ Ac ti veRestClient, Spyke, Flexirest ͳͲ͕͋Δ

Slide 19

Slide 19 text

ਓྨͷྺ࢙: ActiveResource, Her, ... • ͜ΕΒ͸ "Res tf ul API" Λେલఏʹ͓͍͍ͯΔ • ಛఆͷ URL ߏ଄ΛٻΊΒΕΔ • ΍ͬͺΓ JOIN ͸ͦ͜·ͰಘҙͰ΋ͳ͍

Slide 20

Slide 20 text

(2) υϝΠϯڥքʹண໨͢Δ ؔ࿈͢ΔσʔλʹಉҰͷૢ࡞ମܥͰΞΫηεͰ͖Δ ʹ σʔλͷར༻͕ࣗવͳܗͰهड़Ͱ͖Δ 👍 ຊདྷҟͳΔૢ࡞ΛಉҰͷૢ࡞ʹݟ͔͚͍ͤͯΔͷͰ 
 ࣮૷ʹແཧ͕ग़͖͕ͯͪ 🤔

Slide 21

Slide 21 text

(2) υϝΠϯڥքʹண໨͢Δ ؔ࿈͢ΔσʔλʹಉҰͷૢ࡞ମܥͰΞΫηεͰ͖Δ ʹ σʔλͷར༻͕ࣗવͳܗͰهड़Ͱ͖Δ 👍 ຊདྷҟͳΔૢ࡞ΛಉҰͷૢ࡞ʹݟ͔͚͍ͤͯΔͷͰ 
 ࣮૷ʹແཧ͕ग़͖͕ͯͪ 🤔 👊👊 ࣮૷Ͱ৐Γӽ͑Ε͹ղܾ 👊👊

Slide 22

Slide 22 text

ͭͬͯ͘ΈΑ͏ʂ

Slide 23

Slide 23 text

AR ෩ API ΫϥΠΞϯτΛͭͬͯ͘ΈΑ͏ • ֎෦ API ͕ఏڙ͢Δ Recipe ʹ͍ͭͯ • Recipe. fi nd(1) ͷΑ͏ͳܗͰΫΤϦͰ͖Δ • @recipe. ti tle ͷΑ͏ͳܗͰϑΟʔϧυΛಡΊΔ • Ϧιʔεαʔόʔʹಛఆͷߏ଄ (RESTful) Λཁٻ͠ͳ͍ • JOIN (has_many, belongs_to, ...) ΋͏·͘͜ͳͤΔ • Α͏ͳʢجຊతͳʣ΋ͷΛͭͬͯ͘ΈΑ͏

Slide 24

Slide 24 text

ͨͱ͑ AR ෩ʹ͢Δ৔߹Ͱ͋ͬͯ΋ɺτϥϯεϙʔτ͸෼཭͢΂͖ ϦτϥΠॲཧͳͲ͸෼཭͍ͨ͠͠ɺgRPC ҠߦͳͲ΋ָʹͳΔ ·ͣ͸ૢ࡞తͳΫϥΠΞϯτΛ༻ҙ Level 1

Slide 25

Slide 25 text

ͦΕΛ࢖ͬͯ Recipe.find ͰϦΫΤετ Level 1 ҰԠ has_one తͳϝιου ΫΤϦ༻ͷϝιου ( fi nd, where) recipe# ti tle ͳͲͰϑΟʔϧυΞΫηε

Slide 26

Slide 26 text

Controller Ͱผݸʹॲཧ͢Ε͹ճආՄೳͰ͸͋Δ͕…… includes(:recipes) ͷΑ͏ʹهड़͍ͨ͠ ͕͢͞ʹ·࣮ͩ༻త͡Όͳ͍͔΋ User Recipe 
 Contest Recipe Recipe 
 ContestEntry recipes (API) ΛԿ౓΋ϦΫΤετͯ͠͠·͏😔ɹɹɹɹ

Slide 27

Slide 27 text

• Recipe. fi nd ͷ಺෦ͰΩϡʔΠϯά͢Δ • Recipe. fi nd ͔Β͸ͻͱ·ͣ Promise తͳΦϒδΣΫτ͕ฦΔ • exAspArk/batch-loader Λར༻ • Recipe. fi nd ͷฦΓ஋ʹରͯ͠ # ti tle ͳͲΛݺͿͱɺอཹ͞Ε͍ͯͨϦΫΤετ͕·ͱΊͯඈͿ BatchLoader Ͱ eager loading ͢Δ Level 2

Slide 28

Slide 28 text

has_one :recipe Ͱهड़͍ͨ͠…… has_many :recipes Ͱهड़͍ͨ͠……

Slide 29

Slide 29 text

API ΋ຊ෺ͷ ActiveRecord ʹͪ͠Ό͏ Level 3 • ຊ෺ͷ Ac ti veRecord Ϋϥεʹͯ͠͠·͏ 
 ͜ͱͰ has_many, belongs_to ͳͲ͕࢖͑Δ • ͜ͷٕΛ࢖͑Δ͔͸ෆม৚݅࣍ୈ • ͜͜Ͱ͸ "recipe.user_id ͕ෆมͰ͋Δ" • (͔ͭ recipe.user_id ͕ FK Ͱ͋Δ͜ͱ) • ෆม৚݅ͷ෦෼͚ͩςʔϒϧʹೖΕΔ

Slide 30

Slide 30 text

• ݸਓతʹ͸ AR ෩Ͱ͸ͳ͘ɺ΋ͬͱૢ࡞తͳܗ͕ྑ͍ͱࢥ͏ • APIClient.update(id: 1, {name: "nanika"}) • τϥϯβΫγϣϯ͕ඞཁͳΒ1ͭͷDB΁ͷ౷߹Λߟ͑Δ΂͖ • ΫϥΠΞϯτͷߏ଄ʹؔ܎ͳ͘ɺ෼͞ΜτϥϯβΫγϣϯ͸ࠔ೉ ͱ͜ΖͰߋ৽ɾ࡟আ͸ʁ Others

Slide 31

Slide 31 text

མͪึͻΖ͍ɾࡉ͔͍࿩ Others • AR ෩ͷΦϒδΣΫτΛ༻ҙ͢ΔʹͤΑɺescape hatch ͸༻ҙͨ͠΄͏͕͍͍ • Ac ti veModel::Model ʹ͍ͭͯ • ͓޷ΈͰ include ͢ΔͱΑ͍Ͱ͠ΐ͏ • valida ti on ΍ callbacks, rou ti ng ͳͲʹؔ࿈͢Δαϙʔτ͕͍͖ͭͯ·͢ • cookpad/expeditor ͰߋͳΔߴ଎ԽΛૂ͏

Slide 32

Slide 32 text

·ͱΊ ಉҰυϝΠϯͷen ti tyΛಉҰͷૢ࡞ମܥͰѻ͑Δͱؾ͍͍࣋ͪ

Slide 33

Slide 33 text

We are hiring! cookpad.jobs