個人でつくるwebサービス

 個人でつくるwebサービス

銀座Rails#5 での登壇資料です。個人でwebサービスを作るときのtips集及びturbolinks&stimulusの紹介が主な内容です。

https://ginza-rails.connpass.com/event/112093/

6ac7c50770603b53964d44db373e8e48?s=128

Shinichi Maeshima

January 25, 2019
Tweet

Transcript

  1. ݸਓͰͭ͘ΔwebαʔϏε @willnet

  2. ࣗݾ঺հ 4 લౡਅҰ aka @willnet or @netwillnet 4 גࣜձࣾ΢Οϧωοτ(Ұਓձࣾ) 4

    Railsٕज़ސ໰ 4 ۭ͍ͨ࣌ؒͰ savanna.io Λ։ൃ͍ͯ͠·͢
  3. Q. Railsٕज़ސ໰ͬͯͳΜͰ͔͢ A. ϒϩά΍εϥΠυͳͲ͋ΔͷͰͦΕಡΜͰ͍ͩ͘͞ 4 https://blog.willnet.in/entry/2018/04/09/101808 4 https://speakerdeck.com/willnet/ji-shu-gu-wen- toiudong-kifang

  4. Q. savanna.io ͱ͸ 4 4೥൒͘Β͍ίπίπݸਓͰ։ൃ͍ͯ͠ΔwebαʔϏε 4 ͓࢓ࣄ৘ใͰͭͳ͕ΔSNS 4 ॳظͷmixi Έ͍ͨͳট଴੍

  5. None
  6. ࠓ೔࿩͢͜ͱ ओʹsavanna.ioΛ୊ࡐʹͭͭ͠ɺݸਓͰwebαʔϏεΛ࡞Δ ͱ͖ͷtipsʹ͍ͭͯ஻Γ·͢

  7. ݸਓͰwebαʔϏε࡞ΔͷΦεεϝ 4 ݸਓͰRailsΛ࢖ͬͯαʔϏεΛͭ͘Δͷͬͯษڧͱͯ͠࠷ ߴͳΜͰ͢Α 4 ͓࢓ࣄͰ࣮૷͢ΔΑΓ΋ѹ౗తʹτϥΠΞϯυΤϥʔ͕ ΍Γ΍͍͢ 4 ͦ΋ͦ΋Railsͬͯগਓ਺ͰαʔϏε࡞ΔͨΊͷϑϨʔϜ ϫʔΫ

    4 αʔϏεͦͷ΋ͷͷઃܭ΋ָ͍͠
  8. ͔͠͠ݸਓͰαʔϏεΛͭ͘Δͱ͖ ʹ͸େ͖ͳน͕͋ΔͷͰ͢Α ͦΕ͸…

  9. None
  10. Ϟνϕʔγϣϯ͕ͳ͘ͳ ΔཁҼ(ݸਓwebαʔϏε ։ൃฤ)

  11. ৽͍ٕ͠ज़Λ࢖͓͏ͱͯ͠ػೳ௥Ճ ʹΊͬͪΌ࣌ؒΛ͔͚ͯ͠·͏ 4 ษڧ͍ͨ͠ͷ͔ػೳΛ࡞Γ͍ͨͷ͔ 4 ษڧʹภΓ͗͢Δͱਐḿ஗͗ͯ͢΍Δؾ͕ͳ͘ͳͬͯ͘Δ 4 खஈ͕໨తʹͳΔ 4 όϥϯεେࣄ

  12. ຊ࣭తͰͳ͍ͱ͜Ζʹ࣌ؒΛऔΒΕ ͍ͯΔ͏ͪʹ΍Δؾ͕ແ͘ͳͬͯ͘ Δ 4 αʔόͷϝϯςφϯε 4 σϓϩΠ 4 ϥΠϒϥϦͷΞοϓσʔτ 4

    ύϑΥʔϚϯενϡʔχϯά
  13. ݸਓͰۭ͍ͨ࣌ؒʹ΍Δ ͱ͍͏͜ͱ͸ɺ޻਺͕ݶ ΒΕ͍ͯΔͱ͍͏͜ͱ

  14. SaaS(PaaS)ʹ೚ͤΒΕΔ ͱ͜Ζ͸SaaSͰ

  15. heroku 4 ΠϯϑϥΛ·Δͬͱ೚ͤΒΕΔ 4 masterϒϥϯνʹϓογϡͨ͠ΒࣗಈͰσϓϩΠ 4 ϨΠςϯγ͸ɺؾʹͳΔ͘Β͍ͷن໛ײʹͳͬͨΒ͓ۚͰ ղܾ͢Δ༧ఆ 4 Private

    Space
  16. skylight.io 4 ύϑΥʔϚϯεܭଌ༻ 4 10ສϦΫΤετ/݄·Ͱແྉ 4 γϯϓϧͰݟ΍͍͢UI 4 JSͷύϑΥʔϚϯεͳͲ͸ݟΕͳ͍͕ͦ͜͸ଥڠ

  17. codacy 4 ίʔυͷ݈શੑΛνΣοΫ(rubocop, rubycriticΈ͍ͨͳ ΍ͭ) 4 4Ϣʔβ·ͰͳΒແྉ 4 ࣗલͰ࢓૊ΈΛ࡞ΔΑΓָ͔ͭ֬ೝ͠΍͍͢

  18. dependabot 4 ࣗಈͰbundle updateͯ͠PRͯ͘͠ΕΔ 4 ݸਓGitHubΞΧ΢ϯτͰ͋Ε͹privateͰ΋ແྉ 4 gem΍npm1ͭ͝ͱʹ1PR

  19. circleci 4 CI 4 privateϦϙδτϦͰ΋1000෼/݄·Ͱແྉ 4 dependabotΛ࢖͍ͬͯΔͱ1000෼/݄͸ݫ͍͔͠΋

  20. Α͍Saas͋ͬͨΒڭ͑ͯ ͍ͩ͘͞ ‘

  21. ࿩͸มΘͬͯϑϩϯτΤ ϯυ΋खΛൈ͖͍ͨ

  22. jsϑϨʔϜϫʔΫͲΕ͔ͭ͏ʁ 4 react? 4 vue? 4 angular?

  23. ͲΕ΋͍ͨ΁Μͦ͏

  24. ͳΔ΂͘αʔόαΠυͰ ΍Γ͍͕ͨϑϩϯτΤϯ υ΋खؒͳͦ͘ΕͬΆ͍ ײ͡ʹ͍ͨ͠

  25. ͦ͜ͰturbolinksͰ͢Α !

  26. turbolinksͱ͸ 4 rails newͨ͋͠ͱʹ͙͢ফ͢΍ͭ 4 ͳΜ͚ͩͲศརͳΜͰ͢Αʂ 4 ࢖ͬͯΔਓ ! 4

    ͦ΋ͦ΋turbolinksͬͯͳΜͰ͔͢ʁͬͯਓ
  27. None
  28. turbolinksͷ֓ཁ 4 ϖʔδͷϑϧϩʔυΛ͠ͳ͍ͷͰ଎͍ 4 ϒϥ΢βͷཤྺ͸HTML5ͷhistory APIͰΧόʔ

  29. turbolinksͷϝϦοτ 4 গͳ͍खؒͰϢʔβͷମײ଎౓ΛΞοϓͰ͖Δ 4 ٙࣅSPAʹͰ͖Δ 4 αʔόଆͰHTMLΛฦ͠ɺjsΛ࠷খݶʹͱͲΊͯ΋ࠓͲ ͖ͬΆ͍ڍಈʹͳΔ

  30. turbolinksͷࢥ૝

  31. ϦΫΤετ͕ajaxͩͱ Ϣʔβͷମײ଎౓্͕ ͕ͬͯHappy

  32. ָʹϢʔβͷମݧ͕޲্͢ΔͷͰ͋ Ε͹׆༻͍ͨ͠ 4 turbolinks͸ϦϯΫͷΈajaxԽ 4 ϑΥʔϜ΋ajaxʹ͍ͨ͠ 4 form͸form_with͕༻ҙ͞Ε͍ͯΔ 4 σϑΥϧτͰ

    remote: true 4 ʮͳΔ΂͘ajaxʯ͕Rails(ͱ͍͏͔DHH)ͷ͓ؾ࣋ͪ
  33. POSTΛajaxͰϦΫΤετͨͦ͠ͷޙ ͷॲཧ 4 POST͸GET΄Ͳ؆୯ʹ͸࣮૷Ͱ͖ͳ͍ʼʻ 4 history api͕ରԠ͍ͯ͠ͳ͍ 4 turbolinks͸ajax POSTͰͷredirect_toΛαϙʔτͯ͠

    ͘ΕΔ 4 redirect_to Λࠩ͠ସ͑ͯɺTurbolinks.visit()Λ࣮ߦ ͢Δ
  34. όϦσʔγϣϯΤϥʔ 4 DHHతʹ͸ɺajax POSTͰͷόϦσʔγϣϯΤϥʔͷදࣔ ͸खಈͰؤுͬͯͶɺͱ͍͏ଶ౓ 4 ↓͜͏͍͏ͷΛຖճॻ͘ # create.js.erb document.querySelector('#error').innerHTML

    = \ "<%= j(render('error', model: @model)) %>";
  35. ָʹόϦσʔγϣϯΤϥʔΛදࣔ͢ Δgem࡞Γ·ͨ͠ 4 turbolinks&&form_with೿ͷਓ͸࢖ͬͯΈ͍ͯͩ͘͞ 4 https://github.com/willnet/ajax_error_renderer

  36. (๻͸ศརͩͱࢥ͏ͷͰ ͕͢)turbolinks͸શવී ٴͯ͠ͳ͍Α͏ʹࢥΘΕ Δ

  37. turbolinks͕ීٴ͍ͯ͠ͳ͍ཧ༝(ਪ ଌ) 4 ొ৔࣌ɺjqueryϓϥάΠϯͱ૬ੑ͕ѱ͔ͬͨ 4 ࠓ͸reactͳͲͷjsϑϨʔϜϫʔΫ͕ීٴͯ͠͠·ͬͨ 4 ࢓૊ΈΛཧղͤͣʹ࢖͍௧͍໨Λݟͨ 4 ಋೖͷखؒ͸গͳ͍͚Ͳ࢖͍͜ͳ͢ʹ͸ίπ͕ඞཁ

  38. turbolinksΛ࢖ͬͨͱ͖ʹࠔΔ͜ͱ 4 ޙॲཧΛ๨Ε͕ͪ 4 ίʔυ͕෼ࢄ͕ͪ͠ 4 ಛఆͷϖʔδ͚࣮ͩߦ͍ͨ͠ίʔυͷهड़͕൥ࡶʹͳΓ͕ ͪ

  39. ޙॲཧΛ๨Ε͕ͪ 4 savanna.ioͰ࣮ࡍʹ͋ͬͨࣄྫ 4 A͞Μʹૹͬͨ͸ͣͷϝοηʔδ͕B͞ΜʹૹΒΕͯ͠· ͏ʂ !

  40. ࠶ݱखॱ 4 A͞ΜͱͷϝοηʔδϖʔδΛ։͘ 4 B͞Μ΁ͷϝοηʔδϖʔδ΁ભҠͯ͠ɺB͞Μ΁ϝοηʔ δΛૹ৴͢Δ 4 ͢Δͱɺͳ͔ͥA͞Μ΁ϝοηʔδ͕ૹΒΕΔʂ

  41. ίʔυ $(document).on('turbolinks:load', () => { // ͜͜ͰApp.chatͷ࠶࡞੒Λېࢭ͍ͯ͠Δͷ͕ݪҼ if ($('#messages_form').length >

    0 && !App.chat) { App.chat = App.cable.subscriptions.create( { channel: 'ChatChannel', room_code: roomCode }, ...
  42. ϖʔδભҠͯ͠΋άϩʔόϧม਺͸ Ϧηοτ͸͞Εͳ͍ 4 documentͳͲʹඥ͚ͮͨΠϕϯτ΋Ϧηοτ͞Εͳ͍ 4 γϯϓϧͳςετέʔε͚ͩͩͱؾ͚ͮͳ͍ͷͰɺ͋Δఔ ౓शख़͕ඞཁ

  43. ͖ͬ͞ͷίʔυɺͲ͏ղܾͨ͠Βྑ ͍ʁ 4 ͍Ζ͍Ζ໰୊Λճආ͢Δํ๏͸͋Δ͚Ͳɺϝοηʔδ༻ͷ ϖʔδΛ཭ΕΔͱ͖ʹApp.chatΛΫϦΞ͢Δɺͱ͍͏ͷ͕ Ͱ͖Δͱ͖Ε͍Ͱ͢Ͷ 4 ͋ͱͰίʔυग़͠·͢

  44. ಛఆͷϖʔδ͚࣮ͩߦ͍ͨ͠ίʔυ ͷهड़͕൥ࡶʹͳΓ͕ͪ 4 turbolinksΛ࠾༻͢Δͱɺjs͸جຊ1ϑΝΠϧ (application.js)ʹશ෦݁߹ͯ͠഑৴͢Δ͜ͱʹͳΔ 4 ݫີʹ͸turbolinksʹݶΒͳ͍ 4 application.jsʹશ෦٧ΊࠐΉํࣜΛ࠾༻͍ͯ͠Δ৔߹ ͸͍͍ͩͨಉ͡ײ͡ʹͳΔ

  45. ίʔυྫ(erb) લ४උͱͯ͠ɺDOM͔ΒcontrollerͱactionΛ൑ผͰ͖ΔΑ ͏ʹ͓ͯ͘͠ <body class=" #{controller_path.gsub(%r{/}, '-')}_controller #{action_name}_action">

  46. ίʔυྫ(js) $(document).on('turbolinks:load', () => { if ($('.messages_controller').length === 0) {

    return false } // MessagesControllerͰͷΈ࣮ߦ͍ͨ͠ॲཧ
  47. ίʔυ͕ࢄΒ͔Γ͕ͪ turbolinksʹݶΒͣɺಛఆͷjsϑϨʔϜϫʔΫΛ࢖Θͳ͍৔߹ ʹى͜Δ͜ͱ 4 ϑΝΠϧͱίʔυͷରԠ෇͚ͷن໿͕ͳ͍ͷͰόϥόϥʹ ͳΔ 4 users.js͔ͩΒͱ͍ͬͯϢʔβؔ࿈ͷॲཧͷΈͱ͸ݶΒ ͳ͍ 4

    DOMͱjsͱͷରԠ෇͚͕Θ͔Γʹ͍͘
  48. ͭ·Γɺturbolinks͸ศར ͚ͩͲॳ৺ऀʹ͸͓͢͢ ΊͰ͖ͳ͍ʁ

  49. ͱࢥ͍͖΍ɺͦΕΛղܾ ͢ΔͨΊͷϥΠϒϥϦ͕ ͋ΔΜͰ͢Α

  50. stimulus 4 Basecamp੡ 4 ver 1.1.1(ݱ࣌఺) 4 Railsඪ४ϥΠϒϥϦͰ͸ͳ͍͚ͲɺturbolinksͱҰॹʹಈ ͔͢લఏͰ࡞ΒΕ͍ͯΔ 4

    turbolinksͳ͠Ͱ΋࢖͑Δ
  51. stimulusͷϝϦοτ 4 ϑϩϯτΤϯυʹن໿ΛಋೖͰ͖Δ 4 ϧʔϧ͕؆୯Ͱಋೖ͠΍͍͢ 4 ίʔυΛ੔ཧͰ͖Δ

  52. None
  53. stimulusͬ͘͟Γղઆ 4 HTMLͷdata-controllerͷ஋ͱjsଆͷϑΝΠϧ໊͕Ϛο ϐϯά͞Ε࣮ߦ 4 data-actionͰDOMͱjsͷϝιου͕Ϛοϐϯά͞ΕΔ 4 data-targetͰDOMͱjs͕Ϛοϐϯά͞ΕΔ 4 (ίʔυྫʹ͸ࡌͬͯͳ͍͚Ͳ)data-controller͕දࣔ͞

    Εͨͱ͖ɺඇදࣔʹͳͬͨͱ͖ʹϑοΫͯ͠ॲཧΛ͔͚Δ
  54. turbolinks୯ମͰ࢖ͬͨͱ͖ͷ໰୊ ͕ղܾͰ͖Δ લॲཧɺޙॲཧ͕؆୯ʹॻ͚Δ // messages_controller.js export default class extends Controller

    { connect () { this.subscribe() } disconnect () { if (App.chat) { App.cable.subscriptions.remove(App.chat) App.chat = null } }
  55. turbolinks୯ମͰ࢖ͬͨͱ͖ͷ໰୊ ͕ղܾͰ͖Δ 4 DOMͷଐੑΛݟΕ͹ରԠ͢ΔjsͷϑΝΠϧ͕Θ͔Δ 4 DOMͷଐੑΛݟΕ͹jsͰ࢖͍ͬͯΔͷͩͳɺͱΘ͔Δ <div data-controller="hello"> <input data-target="hello.name"

    type="text"> <button data-action="click->hello#greet">Greet</button> <span data-target="hello.output"></span> </div>
  56. turbolinks&stimulusΛ࢖͍ͭͭϑϩ ϯτΤϯυΛ࠷খݶʹ͢Δ 4 ϑϩϯτΤϯυΛָʹ͍͍ײ͡ʹͰ͖Δ 4 ॲཧΛαʔόαΠυʹدͤΔ͜ͱͰ޻਺Λ௿͘Ͱ͖Δ 4 ݸਓ։ൃʹݶΒͣɺϑϩϯτΤϯυϚϯ͕͍ͳ͍͓࢓ࣄͰ ΋ศརʹ࢖͑Δ͔ͱ

  57. ·ͱΊ 4 ݸਓͰϞνϕʔγϣϯΛอͪͭͭ։ൃ͢ΔͨΊͷtipsʹͭ ͍ͯ࿩͠·ͨ͠ 4 ΈΜͳ΋ݸਓͰόϯόϯwebαʔϏε࡞͍͖ͬͯ·͠ΐ͏

  58. ͔͜͜Β͸͕࣌ؒ͋ͬͨ Β࿩͢

  59. ଓ͚ΔͨΊͷݸਓతͳ޻ ෉

  60. ૲ۦಈ։ൃ 4 ࠷௿Ͱ΋1೔1ίϛοτ͢Δ 4 ͕࣌ؒͳ͍೔Ͱ΋ɺࡉ͔͍λεΫΛ1ίϛοτਐΊΔ 4 վળ఺Λݟ͚ͭͨΒIssueʹετοΫ͓ͯ͘͠ 4 ΋͘͠͸େ͖͍ػೳΛ1ίϛοτ෼ਐΊΔ

  61. पΓΛר͖ࠐΉ 4 ڵຯͷ͋Δਓʹख఻ͬͯ΋Β͏ 4 ਐΊ͟ΔΛಘͳ͘ͳΔ 4 ༧ࢉʹ༨༟͕͋Ε͹ɺۀ຿ҕୗͱ͍͏ख΋͋Δ

  62. μϨͳ͍Α͏ʹࣗ෼Λݟ ுΔ

  63. rubocopΛ(΄΅)σϑΥϧτͰ࢖༻ ໰୊ͳ͘։ൃͰ͖Δ 4 class length 100 4 linelength 80 4

    method length 10 4 abcsize 15
  64. ·ͱΊ(ͦͷ2) 4 ܧଓ͢ΔͨΊͷݸਓతͳίπΛ঺հ͠·ͨ͠ 4 ίπɺਓʹΑͬͯҧ͏ͷͰɺࣗ෼ʹ͋ͬͨ΍ΓํͰָ͘͠ ܧଓͰ͖ΔΑ͏ʹؤு͍͖ͬͯ·͠ΐ͏

  65. happy development