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

MOROHASHI Kyosuke

July 14, 2018
Tweet

More Decks by MOROHASHI Kyosuke

Other Decks in Programming

Transcript

  1. ϑΥʔϜΦϒδΣΫτͱͷ

    ޲͖߹͍ํ
    2018-07-11
    Rails Developers Meetup 2018 Day 3 Extreme

    ॾڮګհ @moro


    View Slide

  2. ‣ (ࣸਅ)
    Title


    View Slide



  3. Kyosuke MOROHASHI
    moro moro

    View Slide

  4. View Slide

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


    View Slide



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

    View Slide

  7. ͖ΐ͏ͷ࿩

    View Slide

  8. ‣ “RailsͷΩϨΠͳઃܭ"࠷ॳ͔Β͢΂ͯઃܭ͢Δͷ

    Ή͔͍ͣ͠ͷͰ൓෮ͯ͠࡞ΔͱΑͦ͞͏ɻ
    ‣ ʰॅΈͳ͕Β૿ங͍ͯ͘͠ײ͡ʱ@m_seki

    https://speakerdeck.com/m_seki/re-iterative-development-iteration-4?slide=57
    ‣ Railsʹ͓͍ͯ͸ɺͦͷͱ͔͔ͬΓͱͯ͠ϑΥʔϜʹ

    ண໨͢Δͷ͸ѱ͘ͳͦ͞͏ɻ
    ͖ΐ͏ͷ࿩


    View Slide

  9. എܠ

    View Slide

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


    View Slide

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

    View Slide

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



    View Slide

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


    View Slide

  14. ‣ accept_nested_attributes ͰҰ࿈ͷσʔλΛ

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


    View Slide

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


    View Slide

  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
    ͍ͨ΁ΜͩΑͶɺɺɺͱ͍͏ͷ͕஌ΒΕ͖ͯͨ

    View Slide

  17. ͸͡Ί͔Β
    ͪΌΜͱ
    ઃܭ͢Δͷ͸Ή͔͍ͣ͠


    View Slide

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

    View Slide



  19. View Slide


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

    View Slide

  21. ‣ Webͷೖྗ = request ʹू໿͞Ε͍ͯΔσʔλ
    ‣ ͱͦΕΛಋͨ͘ΊͷϑΥʔϜ΍ͦͷଞը໘
    ‣ϦϯΫͰͷGETભҠ΋ೖྗͱ͍͑͹ೖྗ͚ͩͲɺ

    ͜͜Ͱ͸;Ε·ͤΜɻ
    ‣ඇಉظδϣϒͰ͸ AJ#perform ͷҾ਺΍؀ڥม਺ͳͲ͕

    ೖྗͱͳΔɻ
    RailsͷϓϨθϯςʔγϣϯ


    View Slide

  22. ‣ ʮͦͷଞͷػೳʯ
    ‣ 1ͭҎ্ͷςʔϒϧʹҰ࿈ͷσʔλΛ·ͱΊͯӬଓԽ͢Δ
    ‣ ࿈ܞγεςϜʹ޲͚ͯΠϕϯτΛPub͢Δ
    ‣ ͳͲͳͲ
    RailsͰ͍͏υϝΠϯ


    View Slide

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


    View Slide

  24. ‣ ίϯτϩʔϥʹͯparams͔Β஋ΛऔΓग़͠ɺHash΍

    จࣈྻͱͯ͠ѻ͏ɻ
    ‣ ࣮ଶ͕ AC::Parameters Ͱ΋ Hash ͷΑ͏ʹѻ͏ɻ৺ͷ໨ͰܕΛݟΔ
    ‣ HTTP༝དྷͷσʔλ΋ɺrequest͔ΒऔΓग़͓ͯ͘͠ɻ
    ‣ #user_agent ͱ͔ɺΫοΩʔͷ஋ͱ͔΋
    ೖྗΛ͸͖ͬΓ


    View Slide

  25. ‣ ొ࿥ϖʔδͰϝʔϧΞυϨεΛೖྗͤ͞Δɻ
    ‣ ೖྗ͞ΕͨϝʔϧΞυϨεΛอଘ͢Δ
    ྫ: Ϣʔβʔొ࿥

    View Slide

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

    View Slide

  27. ‣ ίϯτϩʔϥͰऔΓग़ͨ͠஋ͨͪΛೖྗʹ͢Δɻ
    ‣ ୯Ұͷϝιουݺͼग़͠ͰॲཧҰࣜΛ࣮ߦ͢Δɻ
    ‣ ໊લΛ͚ͭΔͷ͸૬มΘΒͣ೉͍͠
    ‣ ಈ໊ࢺʹͨ͠Γɺpre/suffix͚ͭͨΓɺͦͷଞن໿Λಋೖͨ͠Γɻɻɻ
    ‣ ؤுΕ͹ม͑ΒΕΔͷͰɺνʔϜͰͬ͘͠ΓདྷΔ΍ͭʹ͢ΔͱΑ͍ɻ
    ෼͚ΔͨΊͷ૚Λಋೖ͢Δ(ศ্ٓϑΥʔϜΦϒδΣΫτͱݺͼ·͢)


    View Slide


  28. • ಉ͡جຊϓϩάϥϜΛɺॏෳίʔυͳ͠ʹɺෳ਺ͷϓϨθϯςʔγϣϯʹ
    ରԠͤ͞Δ͜ͱ͕Ͱ͖Δ
    • ϢʔβʔΠϯλʔϑΣΠε͸ςετ͕͠ʹ͍ͨ͘ΊɺͦΕΛ෼཭͢Δ͜ͱ
    ʹΑΓɺςετՄೳͳϩδοΫ෦෼ʹूதͰ͖Δ
    • εΫϦϓτ༻ͷ"1*΍αʔϏεͱͯ͠֎෦Խ͢ΔͨΊͷ"1*Λָʹ௥ՃͰ
    ͖Δʢબ୒ՄೳͳϓϨθϯςʔγϣϯ෦෼Ͱݟ͔͚Δʣ
    ϓϨθϯςʔγϣϯͱυϝΠϯͷ෼཭ http://bliki-ja.github.io/PresentationDomainSeparation/

    View Slide

  29. ‣ ͜ͷ”෼͚ΔͨΊͷ૚”΁ͷೖྗ͸POROʹͳΔͷͰɺςε
    τ͔Β؆୯ʹݺͼग़ͤΔɻ
    ‣ PORO: Plain Old Ruby Object = ී௨ͷΦϒδΣΫτ
    ‣ ؆୯ʹݺͼग़ͤΔͷͰɺଞͷςετͰͷσʔληοτΞο
    ϓʹ΋࢖͑Δɻ
    ςετՄೳ


    View Slide

  30. email = '[email protected]'
    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Λϝʔϧ͢Δͷͷςετ


    View Slide

  31. ͜ͷʮϑΥʔϜΦϒδΣΫτʯΛߋʹɺͨͱ͑͹͜Μͳ;͏ʹҭͯͨ͘ͳͬͨͱͯ͠:
    1. ϑΥʔϜΦϒδΣΫτ͸ೖྗϋϯυϦϯάʹͱͲΊɺ

    ӬଓԽͷͨΊʹαʔϏε૚Λ΋͏Ұ૚ઃ͚͍ͨɻ
    2. ϝʔϧૹ৴͸ΤϯςΟςΟӬଓԽΛPub/SubͰݕ஌ͯ͠

    ૄ݁߹ʹ͍ͨ͠ɻ
    “ϩδοΫ෦෼ʹूதͰ͖Δ”


    View Slide

  32. > ӬଓԽͷͨΊʹαʔϏε૚Λઃ͚͍ͨ


    email = '[email protected]'
    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ϨΠϠઃ͚ͯ΋ɺϓϨθϯςʔγϣϯͱͷΠϯ
    λʔϑΣʔε͸มΘΒͣ҆ఆ͍ͯ͠Δɻ

    View Slide

  33. > Pub/SubͰૄ݁߹ʙ


    UserRegistrationForm.new(email: email).call
    + OurJob.execute_all!
    token = extract_token_from_sent_email(AM::Base.deliveries.last)
    ‣ ΠϯλʔϑΣʔε͸҆ఆͨ͠··ɺΞʔΩςΫνϟมߋʹ
    ඞཁͳमਖ਼͚ͩΛೖΕΕ͹Α͍ɻ

    View Slide

  34. ‣ ΠϯλʔϑΣʔε͕҆ఆ͢ΔͷͰɺϩδοΫ෦෼Λ

    มԽ/ચ࿅͢Δࣗ༝౓͕ಘΒΕΔɻ
    ‣ (ಈ࡞͢Δ && !ΩϨΠ) ͳίʔυΛɺ

    (ಈ࡞͢Δ && ΩϨΠ) ͳίʔυʹҭͯΒΕΔɻ
    ‣ ϦϑΝΫλϦϯά!
    “ϩδοΫ෦෼ʹूதͰ͖Δ”


    View Slide

  35. ศ্ٓϑΥʔϜΦϒδΣΫτͱݺΜͩ
    ҙਤ

    View Slide

  36. ‣ A: ͲͬͪͰ΋͍͍
    ‣ ࣗಈςετ͕͋ͬͯϦϑΝΫλϦϯά͠΍͘͢ͳ͍ͬͯΕ͹okɻ
    ‣ ʮೖྗ஋ΛͱΓ·ͱΊͯόϦσʔγϣϯ·ͰΛ͢Δ૚ʯͱɺ

    ʮͦͷvalidͳೖྗ஋ͰॲཧΛ͢Δ૚ʯʹ෼ׂͯ͠΋͍͍Μ͡Όͳ͍͔ͳɻ
    ‣ ࠷ॳʹখ͘͞࡞Δͱ͖UIͱ͚ۙͮͨ΄͏͕͍͍Μ͡Όͳ͍͔ͳ
    ‣ ʮϑΥʔϜʯͬͯͭ·ΓɺαʔϏεΛఏڙ͢Δଆ͕ར༻ऀʹظ଴͢Δ

    ߦಈͦͷ΋ͷͩΑͶɻ
    ‣ ͦ͜ʹԊͬͨ΋ͷΛ࡞Δͷ͕ૉ௚͡Όͳ͍͔ͳɻ
    αʔϏεϨΠϠ͡Όͳͯ͘ϑΥʔϜΦϒδΣΫτਪ͠ͳͷ͸ͳͥ?


    View Slide

  37. ‣ ʮೖྗʯͱʮϩδοΫ෦෼ʯΛ෼͚Α͏
    ‣ ϓϩμΫτίʔυ΋ςετ΋εοΩϦ͢Δ͸ͣ!
    ‣ ࠷ॳ͸খ͘͞φΠʔϒʹ࡞Ζ͏
    ‣ ઃܭ͕Μ͹Γ͗ͯ͢ർΕͳ͍Α͏ʹ…
    ‣ Ͳ͏͍͏ந৅Խ͕ྑ͍ͷ͔ɺ࠷ॳΘ͔Βͳ͍͔ΒͶ
    ‣ ͪΌΜͱ೔ʑϦϑΝΫλϦϯά͠Α͏
    ‣ φΠʔϒͳ··ΰνϟοͱੵΈଓ͚ΔͱͦΕ͸μϝͰ͢Ͷ
    ͲͬͪͰ΋Α͘ͳ͍͜ͱ


    View Slide

  38. ·ͱΊ

    View Slide

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

    ೖྗ஋ͷڥքͱͳΔ͜ͱΛҙࣝ͢Δɻ
    ‣ φΠʔϒ͔ͭςετ͕ॻ͖΍͍͢ϨΠϠ͔Β͸͡Ίͯɺ

    ൓෮͠ͳ͕ΒมԽ͍͚ͯ͠ΔΑ͏ʹ!
    ·ͱΊ


    View Slide