銀座Rails#5 での登壇資料です。個人でwebサービスを作るときのtips集及びturbolinks&stimulusの紹介が主な内容です。
https://ginza-rails.connpass.com/event/112093/
ݸਓͰͭ͘ΔwebαʔϏε@willnet
View Slide
ࣗݾհ4 લౡਅҰ aka @willnet or @netwillnet4 גࣜձࣾΟϧωοτ(Ұਓձࣾ)4 Railsٕज़ސ4 ۭ͍ͨ࣌ؒͰ savanna.io Λ։ൃ͍ͯ͠·͢
Q. Railsٕज़ސͬͯͳΜͰ͔͢A. ϒϩάεϥΠυͳͲ͋ΔͷͰͦΕಡΜͰ͍ͩ͘͞4 https://blog.willnet.in/entry/2018/04/09/1018084 https://speakerdeck.com/willnet/ji-shu-gu-wen-toiudong-kifang
Q. savanna.io ͱ4 4͘Β͍ίπίπݸਓͰ։ൃ͍ͯ͠ΔwebαʔϏε4 ͓ࣄใͰͭͳ͕ΔSNS4 ॳظͷmixiΈ͍ͨͳট੍
ࠓ͢͜ͱओʹsavanna.ioΛࡐʹͭͭ͠ɺݸਓͰwebαʔϏεΛ࡞Δͱ͖ͷtipsʹ͍ͭͯΓ·͢
ݸਓͰwebαʔϏε࡞ΔͷΦεεϝ4 ݸਓͰRailsΛͬͯαʔϏεΛͭ͘Δͷͬͯษڧͱͯ͠࠷ߴͳΜͰ͢Α4 ͓ࣄͰ࣮͢ΔΑΓѹతʹτϥΠΞϯυΤϥʔ͕Γ͍͢4 ͦͦRailsͬͯগਓͰαʔϏε࡞ΔͨΊͷϑϨʔϜϫʔΫ4 αʔϏεͦͷͷͷઃܭָ͍͠
͔͠͠ݸਓͰαʔϏεΛͭ͘Δͱ͖ʹେ͖ͳน͕͋ΔͷͰ͢ΑͦΕ…
Ϟνϕʔγϣϯ͕ͳ͘ͳΔཁҼ(ݸਓwebαʔϏε։ൃฤ)
৽͍ٕ͠ज़Λ͓͏ͱͯ͠ػೳՃʹΊͬͪΌ࣌ؒΛ͔͚ͯ͠·͏4 ษڧ͍ͨ͠ͷ͔ػೳΛ࡞Γ͍ͨͷ͔4 ษڧʹภΓ͗͢Δͱਐḿ͗ͯ͢Δؾ͕ͳ͘ͳͬͯ͘Δ4 खஈ͕తʹͳΔ4 όϥϯεେࣄ
ຊ࣭తͰͳ͍ͱ͜Ζʹ࣌ؒΛऔΒΕ͍ͯΔ͏ͪʹΔؾ͕ແ͘ͳͬͯ͘Δ4 αʔόͷϝϯςφϯε4 σϓϩΠ4 ϥΠϒϥϦͷΞοϓσʔτ4 ύϑΥʔϚϯενϡʔχϯά
ݸਓͰۭ͍ͨ࣌ؒʹΔͱ͍͏͜ͱɺ͕ݶΒΕ͍ͯΔͱ͍͏͜ͱ
SaaS(PaaS)ʹͤΒΕΔͱ͜ΖSaaSͰ
heroku4 ΠϯϑϥΛ·ΔͬͱͤΒΕΔ4 masterϒϥϯνʹϓογϡͨ͠ΒࣗಈͰσϓϩΠ4 ϨΠςϯγɺؾʹͳΔ͘Β͍ͷنײʹͳͬͨΒ͓ۚͰղܾ͢Δ༧ఆ4 Private Space
skylight.io4 ύϑΥʔϚϯεܭଌ༻4 10ສϦΫΤετ/݄·Ͱແྉ4 γϯϓϧͰݟ͍͢UI4 JSͷύϑΥʔϚϯεͳͲݟΕͳ͍͕ͦ͜ଥڠ
codacy4 ίʔυͷ݈શੑΛνΣοΫ(rubocop, rubycriticΈ͍ͨͳͭ)4 4Ϣʔβ·ͰͳΒແྉ4 ࣗલͰΈΛ࡞ΔΑΓָ͔ͭ֬ೝ͍͢͠
dependabot4 ࣗಈͰbundle updateͯ͠PRͯ͘͠ΕΔ4 ݸਓGitHubΞΧϯτͰ͋ΕprivateͰແྉ4 gemnpm1ͭ͝ͱʹ1PR
circleci4 CI4 privateϦϙδτϦͰ1000/݄·Ͱແྉ4 dependabotΛ͍ͬͯΔͱ1000/݄ݫ͍͔͠
Α͍Saas͋ͬͨΒڭ͍͑ͯͩ͘͞ ‘
มΘͬͯϑϩϯτΤϯυखΛൈ͖͍ͨ
jsϑϨʔϜϫʔΫͲΕ͔ͭ͏ʁ4 react?4 vue?4 angular?
ͲΕ͍ͨΜͦ͏
ͳΔ͘αʔόαΠυͰΓ͍͕ͨϑϩϯτΤϯυखؒͳͦ͘ΕͬΆ͍ײ͡ʹ͍ͨ͠
ͦ͜ͰturbolinksͰ͢Α!
turbolinksͱ4 rails newͨ͋͠ͱʹ͙͢ফͭ͢4 ͳΜ͚ͩͲศརͳΜͰ͢Αʂ4 ͬͯΔਓ!4 ͦͦturbolinksͬͯͳΜͰ͔͢ʁͬͯਓ
turbolinksͷ֓ཁ4 ϖʔδͷϑϧϩʔυΛ͠ͳ͍ͷͰ͍4 ϒϥβͷཤྺHTML5ͷhistory APIͰΧόʔ
turbolinksͷϝϦοτ4 গͳ͍खؒͰϢʔβͷମײΛΞοϓͰ͖Δ4 ٙࣅSPAʹͰ͖Δ4 αʔόଆͰHTMLΛฦ͠ɺjsΛ࠷খݶʹͱͲΊͯࠓͲ͖ͬΆ͍ڍಈʹͳΔ
turbolinksͷࢥ
ϦΫΤετ͕ajaxͩͱϢʔβͷମײ্͕͕ͬͯHappy
ָʹϢʔβͷମݧ্͕͢ΔͷͰ͋Ε׆༻͍ͨ͠4 turbolinksϦϯΫͷΈajaxԽ4 ϑΥʔϜajaxʹ͍ͨ͠4 formform_with͕༻ҙ͞Ε͍ͯΔ4 σϑΥϧτͰ remote: true4 ʮͳΔ͘ajaxʯ͕Rails(ͱ͍͏͔DHH)ͷ͓ؾ࣋ͪ
POSTΛajaxͰϦΫΤετͨͦ͠ͷޙͷॲཧ4 POSTGET΄Ͳ؆୯ʹ࣮Ͱ͖ͳ͍ʼʻ4 history api͕ରԠ͍ͯ͠ͳ͍4 turbolinksajax POSTͰͷredirect_toΛαϙʔτͯ͘͠ΕΔ4 redirect_to Λࠩ͠ସ͑ͯɺTurbolinks.visit()Λ࣮ߦ͢Δ
όϦσʔγϣϯΤϥʔ4 DHHతʹɺajax POSTͰͷόϦσʔγϣϯΤϥʔͷදࣔखಈͰؤுͬͯͶɺͱ͍͏ଶ4 ↓͜͏͍͏ͷΛຖճॻ͘# create.js.erbdocument.querySelector('#error').innerHTML = \"<%= j(render('error', model: @model)) %>";
ָʹόϦσʔγϣϯΤϥʔΛදࣔ͢Δgem࡞Γ·ͨ͠4 turbolinks&&form_withͷਓͬͯΈ͍ͯͩ͘͞4 https://github.com/willnet/ajax_error_renderer
(ศརͩͱࢥ͏ͷͰ͕͢)turbolinksશવීٴͯ͠ͳ͍Α͏ʹࢥΘΕΔ
turbolinks͕ීٴ͍ͯ͠ͳ͍ཧ༝(ਪଌ)4 ొ࣌ɺjqueryϓϥάΠϯͱ૬ੑ͕ѱ͔ͬͨ4 ࠓreactͳͲͷjsϑϨʔϜϫʔΫ͕ීٴͯ͠͠·ͬͨ4 ΈΛཧղͤͣʹ͍௧͍Λݟͨ4 ಋೖͷखؒগͳ͍͚Ͳ͍͜ͳ͢ʹίπ͕ඞཁ
turbolinksΛͬͨͱ͖ʹࠔΔ͜ͱ4 ޙॲཧΛΕ͕ͪ4 ίʔυ͕ࢄ͕ͪ͠4 ಛఆͷϖʔδ͚࣮ͩߦ͍ͨ͠ίʔυͷهड़͕ࡶʹͳΓ͕ͪ
ޙॲཧΛΕ͕ͪ4 savanna.ioͰ࣮ࡍʹ͋ͬͨࣄྫ4 A͞Μʹૹͬͨͣͷϝοηʔδ͕B͞ΜʹૹΒΕͯ͠·͏ʂ!
࠶ݱखॱ4 A͞ΜͱͷϝοηʔδϖʔδΛ։͘4 B͞ΜͷϝοηʔδϖʔδભҠͯ͠ɺB͞ΜϝοηʔδΛૹ৴͢Δ4 ͢Δͱɺͳ͔ͥA͞Μϝοηʔδ͕ૹΒΕΔʂ
ίʔυ$(document).on('turbolinks:load', () => {// ͜͜ͰApp.chatͷ࠶࡞Λېࢭ͍ͯ͠Δͷ͕ݪҼif ($('#messages_form').length > 0 && !App.chat) {App.chat = App.cable.subscriptions.create({channel: 'ChatChannel',room_code: roomCode},...
ϖʔδભҠͯ͠άϩʔόϧมϦηοτ͞Εͳ͍4 documentͳͲʹඥ͚ͮͨΠϕϯτϦηοτ͞Εͳ͍4 γϯϓϧͳςετέʔε͚ͩͩͱؾ͚ͮͳ͍ͷͰɺ͋Δఔशख़͕ඞཁ
͖ͬ͞ͷίʔυɺͲ͏ղܾͨ͠Βྑ͍ʁ4 ͍Ζ͍ΖΛճආ͢Δํ๏͋Δ͚Ͳɺϝοηʔδ༻ͷϖʔδΛΕΔͱ͖ʹApp.chatΛΫϦΞ͢Δɺͱ͍͏ͷ͕Ͱ͖Δͱ͖Ε͍Ͱ͢Ͷ4 ͋ͱͰίʔυग़͠·͢
ಛఆͷϖʔδ͚࣮ͩߦ͍ͨ͠ίʔυͷهड़͕ࡶʹͳΓ͕ͪ4 turbolinksΛ࠾༻͢Δͱɺjsجຊ1ϑΝΠϧ(application.js)ʹશ෦݁߹ͯ͠৴͢Δ͜ͱʹͳΔ4 ݫີʹturbolinksʹݶΒͳ͍4 application.jsʹશ෦٧ΊࠐΉํࣜΛ࠾༻͍ͯ͠Δ߹͍͍ͩͨಉ͡ײ͡ʹͳΔ
ίʔυྫ(erb)લ४උͱͯ͠ɺDOM͔ΒcontrollerͱactionΛผͰ͖ΔΑ͏ʹ͓ͯ͘͠
ίʔυྫ(js)$(document).on('turbolinks:load', () => {if ($('.messages_controller').length === 0) {return false}// MessagesControllerͰͷΈ࣮ߦ͍ͨ͠ॲཧ
ίʔυ͕ࢄΒ͔Γ͕ͪturbolinksʹݶΒͣɺಛఆͷjsϑϨʔϜϫʔΫΛΘͳ͍߹ʹى͜Δ͜ͱ4 ϑΝΠϧͱίʔυͷରԠ͚ͷن͕ͳ͍ͷͰόϥόϥʹͳΔ4 users.js͔ͩΒͱ͍ͬͯϢʔβؔ࿈ͷॲཧͷΈͱݶΒͳ͍4 DOMͱjsͱͷରԠ͚͕Θ͔Γʹ͍͘
ͭ·Γɺturbolinksศར͚ͩͲॳ৺ऀʹ͓͢͢ΊͰ͖ͳ͍ʁ
ͱࢥ͍͖ɺͦΕΛղܾ͢ΔͨΊͷϥΠϒϥϦ͕͋ΔΜͰ͢Α
stimulus4 Basecamp4 ver 1.1.1(ݱ࣌)4 Railsඪ४ϥΠϒϥϦͰͳ͍͚ͲɺturbolinksͱҰॹʹಈ͔͢લఏͰ࡞ΒΕ͍ͯΔ4 turbolinksͳ͠Ͱ͑Δ
stimulusͷϝϦοτ4 ϑϩϯτΤϯυʹنΛಋೖͰ͖Δ4 ϧʔϧ͕؆୯Ͱಋೖ͍͢͠4 ίʔυΛཧͰ͖Δ
stimulusͬ͘͟Γղઆ4 HTMLͷdata-controllerͷͱjsଆͷϑΝΠϧ໊͕Ϛοϐϯά͞Ε࣮ߦ4 data-actionͰDOMͱjsͷϝιου͕Ϛοϐϯά͞ΕΔ4 data-targetͰDOMͱjs͕Ϛοϐϯά͞ΕΔ4 (ίʔυྫʹࡌͬͯͳ͍͚Ͳ)data-controller͕දࣔ͞Εͨͱ͖ɺඇදࣔʹͳͬͨͱ͖ʹϑοΫͯ͠ॲཧΛ͔͚Δ
turbolinks୯ମͰͬͨͱ͖ͷ͕ղܾͰ͖Δલॲཧɺޙॲཧ͕؆୯ʹॻ͚Δ// messages_controller.jsexport default class extends Controller {connect () {this.subscribe()}disconnect () {if (App.chat) {App.cable.subscriptions.remove(App.chat)App.chat = null}}
turbolinks୯ମͰͬͨͱ͖ͷ͕ղܾͰ͖Δ4 DOMͷଐੑΛݟΕରԠ͢ΔjsͷϑΝΠϧ͕Θ͔Δ4 DOMͷଐੑΛݟΕjsͰ͍ͬͯΔͷͩͳɺͱΘ͔ΔGreet
turbolinks&stimulusΛ͍ͭͭϑϩϯτΤϯυΛ࠷খݶʹ͢Δ4 ϑϩϯτΤϯυΛָʹ͍͍ײ͡ʹͰ͖Δ4 ॲཧΛαʔόαΠυʹدͤΔ͜ͱͰΛ͘Ͱ͖Δ4 ݸਓ։ൃʹݶΒͣɺϑϩϯτΤϯυϚϯ͕͍ͳ͍͓ࣄͰศརʹ͑Δ͔ͱ
·ͱΊ4 ݸਓͰϞνϕʔγϣϯΛอͪͭͭ։ൃ͢ΔͨΊͷtipsʹ͍ͭͯ͠·ͨ͠4 ΈΜͳݸਓͰόϯόϯwebαʔϏε࡞͍͖ͬͯ·͠ΐ͏
͔͜͜Β͕࣌ؒ͋ͬͨΒ͢
ଓ͚ΔͨΊͷݸਓతͳ
ۦಈ։ൃ4 ࠷Ͱ11ίϛοτ͢Δ4 ͕࣌ؒͳ͍Ͱɺࡉ͔͍λεΫΛ1ίϛοτਐΊΔ4 վળΛݟ͚ͭͨΒIssueʹετοΫ͓ͯ͘͠4 ͘͠େ͖͍ػೳΛ1ίϛοτਐΊΔ
पΓΛר͖ࠐΉ4 ڵຯͷ͋ΔਓʹखͬͯΒ͏4 ਐΊ͟ΔΛಘͳ͘ͳΔ4 ༧ࢉʹ༨༟͕͋Εɺۀҕୗͱ͍͏ख͋Δ
μϨͳ͍Α͏ʹࣗΛݟுΔ
rubocopΛ(΄΅)σϑΥϧτͰ༻ͳ͘։ൃͰ͖Δ4 class length 1004 linelength 804 method length 104 abcsize 15
·ͱΊ(ͦͷ2)4 ܧଓ͢ΔͨΊͷݸਓతͳίπΛհ͠·ͨ͠4 ίπɺਓʹΑͬͯҧ͏ͷͰɺࣗʹ͋ͬͨΓํͰָ͘͠ܧଓͰ͖ΔΑ͏ʹؤு͍͖ͬͯ·͠ΐ͏
happy development