Upgrade to Pro — share decks privately, control downloads, hide ads and more …

フォームオブジェクトとの向き合い方/Grow Form Objects up

フォームオブジェクトとの向き合い方/Grow Form Objects up

Talk at Rails DM Day3 extreme

See also https://railsdm.herokuapp.com/issues/78

70e13d9877054026fda46d5a5b53a236?s=128

MOROHASHI Kyosuke

July 14, 2018
Tweet

Transcript

  1. ϑΥʔϜΦϒδΣΫτͱͷ
 ޲͖߹͍ํ 2018-07-11 Rails Developers Meetup 2018 Day 3 Extreme


    ॾڮګհ @moro  
  2. ‣ (ࣸਅ) Title  

  3.   Kyosuke MOROHASHI moro moro

  4. None
  5. גࣜձࣾΤεɾΤϜɾΤε ೥૑ۀɺ೥౦ূҰ෦্৔ɻ ߴྸࣾձΛհޢɾҩྍɾΩϟϦΞɾϔϧεέΞɾ γχΞϥΠϑͱଊ͑ɺߴྸࣾձʹదͨ͠৘ใαʔ ϏεΛଟ਺։ൃɾӡӦ  

  6.   https://www.wantedly.com/companies/sms

  7. ͖ΐ͏ͷ࿩

  8. ‣ “RailsͷΩϨΠͳઃܭ"࠷ॳ͔Β͢΂ͯઃܭ͢Δͷ
 Ή͔͍ͣ͠ͷͰ൓෮ͯ͠࡞ΔͱΑͦ͞͏ɻ ‣ ʰॅΈͳ͕Β૿ங͍ͯ͘͠ײ͡ʱ@m_seki
 https://speakerdeck.com/m_seki/re-iterative-development-iteration-4?slide=57 ‣ Railsʹ͓͍ͯ͸ɺͦͷͱ͔͔ͬΓͱͯ͠ϑΥʔϜʹ
 ண໨͢Δͷ͸ѱ͘ͳͦ͞͏ɻ ͖ΐ͏ͷ࿩

     
  9. എܠ

  10. ‣ DBͷςʔϒϧʹ΄΅Ұகͨ͠ߏ଄ͷσʔλ͕POST͞Εͯ ͖ͯɺͦΕΛARͰγϯϓϧʹӬଓԽ͢Δɻ ‣ ͳ͔ͳ͔ͦ͏΋ߦ͔ͳ͍͜ͱ΋ଟ͍ΑͶɻ ૉ๿ͳRails͕૝ఆ͍ͯ͠Δ͜ͱ  

  11. ‣ Ϣʔβʔ͕໨ʹ͢Δ৘ใ୯Ґ(≒ϑΥʔϜͷߏ੒)ͱɺਖ਼نԽ ͞Εͨσʔλߏ଄͸ҟͳΔɻ ‣ DBʹӬଓԽ͢Δ͚ͩͰ͸ࡁ·ͳ͍͜ͱ͕͋Δɻ ‣ ϝʔϧΛૹΔɺϩάΛऔΔɺඇಉظδϣϒΛΩοΫ͢Δɺ Πϕϯτͱͯ͠Publish͢ΔɺɺɺͳͲͳͲ “ͦ͏΋ߦ͔ͳ͍͜ͱ”

  12. ࠩҟΛຒΊΔςΫχοΫ ͏·͘ߦ͖ͦ͏͚ͩͲͬ͘͠Γ͜ͳ͍΍ͭ  

  13. ‣ ίϯτϩʔϥʔͰARϞσϧʹ٧Ί௚͢ɻ ‣ ͍ΘΏΔFat ControllerʹͳΓ͕ͪ ‣ ͷͰϞσϧʹدͤΔɺͱFat Model ‣ ·͍͍͋ͯ͑͠͹Ϟσϧ͕Ͱ͔͍΄͏͕·ͩϚγ…

    ࠩҟΛຒΊΔςΫχοΫ  
  14. ‣ accept_nested_attributes ͰҰ࿈ͷσʔλΛ
 ·ͱΊͯೖྗͤ͞Δ ‣ ϑΥʔϜ΍ίϯτϩʔϥʹɺӬଓԽ૚ͷσʔλάϥϑ͕࿐ग़͢Δ ‣ ͓͢͢Ί͠·ͤΜɻ ࠩҟΛຒΊΔςΫχοΫ 

    
  15. ‣ ʮӬଓԽ͢Δ͚ͩʯͰͳ͍ॲཧΛίʔϧόοΫͱ࣮ͯ͠ݱ ͢Δɻ ‣ ίϧόοΫ͍ͨ͠ͱ͖ͱɺ୯ʹσʔλΛอଘ͍ͨ͠ͱ͖ͷหผ͕͍ͨ΁Μ ‣ ίʔϧόοΫʹͨ͘͞Μͷ if ͕Ͱ͖ͯ͘Δͷ͕༧ஹ ࠩҟΛຒΊΔςΫχοΫ

     
  16. ‣ 7 Patterns to Refactor Fat ActiveRecord Models ‣ https://codeclimate.com/blog/7-ways-to-decompose-fat-

    activerecord-models/ ‣Realworld Domain Model on Rails ‣ https://speakerdeck.com/joker1007/realworld-domain- model-on-rails ͍ͨ΁ΜͩΑͶɺɺɺͱ͍͏ͷ͕஌ΒΕ͖ͯͨ
  17. ͸͡Ί͔Β ͪΌΜͱ ઃܭ͢Δͷ͸Ή͔͍ͣ͠  

  18. ܧଓతʹҭͯΔҰา໨

  19.  

  20. “ ࠷΋༗༻ͳઃܭݪଇʹɺϓϩάϥϜʢϢʔ βʔΠϯλʔϑΣΠεʣͷϓϨθϯςʔγϣ ϯ૚ͱͦͷଞͷػೳΛ͏·͘෼͚Δɺͱ͍ ͏ͷ͕͋Γ·͢ɻ ϓϨθϯςʔγϣϯͱυϝΠϯͷ෼཭ http://bliki-ja.github.io/PresentationDomainSeparation/

  21. ‣ Webͷೖྗ = request ʹू໿͞Ε͍ͯΔσʔλ ‣ ͱͦΕΛಋͨ͘ΊͷϑΥʔϜ΍ͦͷଞը໘ ‣ϦϯΫͰͷGETભҠ΋ೖྗͱ͍͑͹ೖྗ͚ͩͲɺ
 ͜͜Ͱ͸;Ε·ͤΜɻ ‣ඇಉظδϣϒͰ͸

    AJ#perform ͷҾ਺΍؀ڥม਺ͳͲ͕
 ೖྗͱͳΔɻ RailsͷϓϨθϯςʔγϣϯ  
  22. ‣ ʮͦͷଞͷػೳʯ ‣ 1ͭҎ্ͷςʔϒϧʹҰ࿈ͷσʔλΛ·ͱΊͯӬଓԽ͢Δ ‣ ࿈ܞγεςϜʹ޲͚ͯΠϕϯτΛPub͢Δ ‣ ͳͲͳͲ RailsͰ͍͏υϝΠϯ 

    
  23. ‣ ϓϨθϯςʔγϣϯͷ஌͕ࣝɺʮͦͷଞͷػೳʯʹϦʔΫ ͠ͳ͍Α͏ʹɻ·ͣ͸ೖྗΛ͸͖ͬΓͤ͞Δɻ ʮ͏·͘ʯ෼͚Δ  

  24. ‣ ίϯτϩʔϥʹͯparams͔Β஋ΛऔΓग़͠ɺHash΍
 จࣈྻͱͯ͠ѻ͏ɻ ‣ ࣮ଶ͕ AC::Parameters Ͱ΋ Hash ͷΑ͏ʹѻ͏ɻ৺ͷ໨ͰܕΛݟΔ ‣

    HTTP༝དྷͷσʔλ΋ɺrequest͔ΒऔΓग़͓ͯ͘͠ɻ ‣ #user_agent ͱ͔ɺΫοΩʔͷ஋ͱ͔΋ ೖྗΛ͸͖ͬΓ  
  25. ‣ ొ࿥ϖʔδͰϝʔϧΞυϨεΛೖྗͤ͞Δɻ ‣ ೖྗ͞ΕͨϝʔϧΞυϨεΛอଘ͢Δ ྫ: Ϣʔβʔొ࿥

  26. ‣ ࣮ࡏ֬ೝ༻ͷURLτʔΫϯ΋Ұॹʹอଘ͢Δɻ ‣ ͜Ε͸ after create ίʔϧόοΫͰ΍Δ͜ͱ΋ଟ͍͠ɺͦΕ͚ͩͳΒ͞΄ͲࠔΒͳ͍͚Ͳ΋ɻ ‣ τʔΫϯΛؚΉURLΛϝʔϧͰૹ৴͢Δɻ ‣

    ͜ΕΛίʔϧόοΫͰ΍ΔͱՒࠜʹͳΓ͕ͪɻ ྫ: AR͚ͩͰ·͔ͳ͍ͮΒ͍ʮ΍Δ͜ͱʯ
  27. ‣ ίϯτϩʔϥͰऔΓग़ͨ͠஋ͨͪΛೖྗʹ͢Δɻ ‣ ୯Ұͷϝιουݺͼग़͠ͰॲཧҰࣜΛ࣮ߦ͢Δɻ ‣ ໊લΛ͚ͭΔͷ͸૬มΘΒͣ೉͍͠ ‣ ಈ໊ࢺʹͨ͠Γɺpre/suffix͚ͭͨΓɺͦͷଞن໿Λಋೖͨ͠Γɻɻɻ ‣ ؤுΕ͹ม͑ΒΕΔͷͰɺνʔϜͰͬ͘͠ΓདྷΔ΍ͭʹ͢ΔͱΑ͍ɻ

    ෼͚ΔͨΊͷ૚Λಋೖ͢Δ(ศ্ٓϑΥʔϜΦϒδΣΫτͱݺͼ·͢)  
  28. “ • ಉ͡جຊϓϩάϥϜΛɺॏෳίʔυͳ͠ʹɺෳ਺ͷϓϨθϯςʔγϣϯʹ ରԠͤ͞Δ͜ͱ͕Ͱ͖Δ • ϢʔβʔΠϯλʔϑΣΠε͸ςετ͕͠ʹ͍ͨ͘ΊɺͦΕΛ෼཭͢Δ͜ͱ ʹΑΓɺςετՄೳͳϩδοΫ෦෼ʹूதͰ͖Δ • εΫϦϓτ༻ͷ"1*΍αʔϏεͱͯ͠֎෦Խ͢ΔͨΊͷ"1*Λָʹ௥ՃͰ ͖Δʢબ୒ՄೳͳϓϨθϯςʔγϣϯ෦෼Ͱݟ͔͚Δʣ

    ϓϨθϯςʔγϣϯͱυϝΠϯͷ෼཭ http://bliki-ja.github.io/PresentationDomainSeparation/
  29. ‣ ͜ͷ”෼͚ΔͨΊͷ૚”΁ͷೖྗ͸POROʹͳΔͷͰɺςε τ͔Β؆୯ʹݺͼग़ͤΔɻ ‣ PORO: Plain Old Ruby Object =

    ී௨ͷΦϒδΣΫτ ‣ ؆୯ʹݺͼग़ͤΔͷͰɺଞͷςετͰͷσʔληοτΞο ϓʹ΋࢖͑Δɻ ςετՄೳ  
  30. email = 'hi@example.com' form = UserRegistrationForm.new(email: email) form.call token =

    extract_token_from_sent_email(AM::Base.deliveries.last) expect(token).not_to be_nil expect(UserRegistration.find_by(email: email, uuid: token)).to be_present ྫ1: ೖྗ͞ΕͨϝΞυΛอଘͯ֬͠ೝURLΛϝʔϧ͢Δͷͷςετ  
  31. ͜ͷʮϑΥʔϜΦϒδΣΫτʯΛߋʹɺͨͱ͑͹͜Μͳ;͏ʹҭͯͨ͘ͳͬͨͱͯ͠: 1. ϑΥʔϜΦϒδΣΫτ͸ೖྗϋϯυϦϯάʹͱͲΊɺ
 ӬଓԽͷͨΊʹαʔϏε૚Λ΋͏Ұ૚ઃ͚͍ͨɻ 2. ϝʔϧૹ৴͸ΤϯςΟςΟӬଓԽΛPub/SubͰݕ஌ͯ͠
 ૄ݁߹ʹ͍ͨ͠ɻ “ϩδοΫ෦෼ʹूதͰ͖Δ”  

  32. > ӬଓԽͷͨΊʹαʔϏε૚Λઃ͚͍ͨ   email = 'hi@example.com' form = UserRegistrationForm.new(email:

    email) form.call token = extract_token_from_sent_email(AM::Base.deliveries.last) expect(token).not_to be_nil expect(UserRegistration.find_by(email: email, uuid: token)).to be_present ‣ ಺෦ʹ΋͏1ϨΠϠઃ͚ͯ΋ɺϓϨθϯςʔγϣϯͱͷΠϯ λʔϑΣʔε͸มΘΒͣ҆ఆ͍ͯ͠Δɻ
  33. > Pub/SubͰૄ݁߹ʙ   UserRegistrationForm.new(email: email).call + OurJob.execute_all! token =

    extract_token_from_sent_email(AM::Base.deliveries.last) ‣ ΠϯλʔϑΣʔε͸҆ఆͨ͠··ɺΞʔΩςΫνϟมߋʹ ඞཁͳमਖ਼͚ͩΛೖΕΕ͹Α͍ɻ
  34. ‣ ΠϯλʔϑΣʔε͕҆ఆ͢ΔͷͰɺϩδοΫ෦෼Λ
 มԽ/ચ࿅͢Δࣗ༝౓͕ಘΒΕΔɻ ‣ (ಈ࡞͢Δ && !ΩϨΠ) ͳίʔυΛɺ
 (ಈ࡞͢Δ &&

    ΩϨΠ) ͳίʔυʹҭͯΒΕΔɻ ‣ ϦϑΝΫλϦϯά! “ϩδοΫ෦෼ʹूதͰ͖Δ”  
  35. ศ্ٓϑΥʔϜΦϒδΣΫτͱݺΜͩ ҙਤ

  36. ‣ A: ͲͬͪͰ΋͍͍ ‣ ࣗಈςετ͕͋ͬͯϦϑΝΫλϦϯά͠΍͘͢ͳ͍ͬͯΕ͹okɻ ‣ ʮೖྗ஋ΛͱΓ·ͱΊͯόϦσʔγϣϯ·ͰΛ͢Δ૚ʯͱɺ
 ʮͦͷvalidͳೖྗ஋ͰॲཧΛ͢Δ૚ʯʹ෼ׂͯ͠΋͍͍Μ͡Όͳ͍͔ͳɻ ‣ ࠷ॳʹখ͘͞࡞Δͱ͖UIͱ͚ۙͮͨ΄͏͕͍͍Μ͡Όͳ͍͔ͳ

    ‣ ʮϑΥʔϜʯͬͯͭ·ΓɺαʔϏεΛఏڙ͢Δଆ͕ར༻ऀʹظ଴͢Δ
 ߦಈͦͷ΋ͷͩΑͶɻ ‣ ͦ͜ʹԊͬͨ΋ͷΛ࡞Δͷ͕ૉ௚͡Όͳ͍͔ͳɻ αʔϏεϨΠϠ͡Όͳͯ͘ϑΥʔϜΦϒδΣΫτਪ͠ͳͷ͸ͳͥ?  
  37. ‣ ʮೖྗʯͱʮϩδοΫ෦෼ʯΛ෼͚Α͏ ‣ ϓϩμΫτίʔυ΋ςετ΋εοΩϦ͢Δ͸ͣ! ‣ ࠷ॳ͸খ͘͞φΠʔϒʹ࡞Ζ͏ ‣ ઃܭ͕Μ͹Γ͗ͯ͢ർΕͳ͍Α͏ʹ… ‣ Ͳ͏͍͏ந৅Խ͕ྑ͍ͷ͔ɺ࠷ॳΘ͔Βͳ͍͔ΒͶ

    ‣ ͪΌΜͱ೔ʑϦϑΝΫλϦϯά͠Α͏ ‣ φΠʔϒͳ··ΰνϟοͱੵΈଓ͚ΔͱͦΕ͸μϝͰ͢Ͷ ͲͬͪͰ΋Α͘ͳ͍͜ͱ  
  38. ·ͱΊ

  39. ‣ Ϗϡʔ / ίϯτϩʔϥ / AR::B ͷࡾ૬ߏ଄Ͱ·͔ͳ͑ͳͦ͏ ͳ৔߹ɺബ͍૚Λ΋͏Ұ૚࡞ͬͯΈΔͱΑ͍ɻ ‣ ίϯτϩʔϥ͕ѻ͏Webͷೖྗ஋ͱɺϩδοΫʹඞཁͳ


    ೖྗ஋ͷڥքͱͳΔ͜ͱΛҙࣝ͢Δɻ ‣ φΠʔϒ͔ͭςετ͕ॻ͖΍͍͢ϨΠϠ͔Β͸͡Ίͯɺ
 ൓෮͠ͳ͕ΒมԽ͍͚ͯ͠ΔΑ͏ʹ! ·ͱΊ