Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
フォームオブジェクトとの向き合い方/Grow Form Objects up
Search
MOROHASHI Kyosuke
July 14, 2018
Programming
1
2k
フォームオブジェクトとの向き合い方/Grow Form Objects up
Talk at Rails DM Day3 extreme
See also
https://railsdm.herokuapp.com/issues/78
MOROHASHI Kyosuke
July 14, 2018
Tweet
Share
More Decks by MOROHASHI Kyosuke
See All by MOROHASHI Kyosuke
Identifying User Idenity
moro
9
15k
Simplicity on Rails -- RDB, REST and Ruby
moro
14
17k
ちょうどよい Rails E2E テスト/enough-good-rails-e2e-test
moro
5
2.4k
フレームワークを作らない方法/How NOT to build frameworks
moro
4
1.1k
全体がいい感じになるために、私たちRailsをホームにするWeb技術者ができること/let-our-whole-system-grow
moro
2
1.9k
チームによるいきいきとしたソフトウェア開発/an-alive-team-grows-software
moro
3
3.3k
Web-E2E-Testing-from-Ruby
moro
5
530
Joyful user foundation restructuring with Ruby
moro
9
19k
cookpad-17day-tech-internship-2017-git
moro
0
9.4k
Other Decks in Programming
See All in Programming
Kubernetes History Inspector(KHI)を触ってみた
bells17
0
250
Introduction to kotlinx.rpc
arawn
0
750
PHP ステートレス VS ステートフル 状態管理と並行性 / php-stateless-stateful
ytake
0
110
ナレッジイネイブリングにAIを活用してみる ゆるSRE勉強会 #9
nealle
0
120
データベースのオペレーターであるCloudNativePGがStatefulSetを使わない理由に迫る
nnaka2992
0
230
GoとPHPのインターフェイスの違い
shimabox
2
200
コードを読んで理解するko build
bells17
1
100
Go 1.24でジェネリックになった型エイリアスの紹介
syumai
2
260
負債になりにくいCSSをデザイナとつくるには?
fsubal
10
2.5k
Rubyで始める関数型ドメインモデリング
shogo_tksk
0
130
Ça bouge du côté des animations CSS !
goetter
2
140
Conform を推す - Advocating for Conform
mizoguchicoji
3
710
Featured
See All Featured
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
40
2k
YesSQL, Process and Tooling at Scale
rocio
172
14k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
507
140k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
226
22k
A designer walks into a library…
pauljervisheath
205
24k
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
4
360
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
6
570
Facilitating Awesome Meetings
lara
52
6.2k
The Power of CSS Pseudo Elements
geoffreycrofte
75
5.5k
Product Roadmaps are Hard
iamctodd
PRO
50
11k
Fontdeck: Realign not Redesign
paulrobertlloyd
83
5.4k
Rebuilding a faster, lazier Slack
samanthasiow
80
8.8k
Transcript
ϑΥʔϜΦϒδΣΫτͱͷ ͖߹͍ํ 2018-07-11 Rails Developers Meetup 2018 Day 3 Extreme
ॾڮګհ @moro
‣ (ࣸਅ) Title
Kyosuke MOROHASHI moro moro
None
גࣜձࣾΤεɾΤϜɾΤε ۀɺ౦ূҰ෦্ɻ ߴྸࣾձΛհޢɾҩྍɾΩϟϦΞɾϔϧεέΞɾ γχΞϥΠϑͱଊ͑ɺߴྸࣾձʹదͨ͠ใαʔ ϏεΛଟ։ൃɾӡӦ
https://www.wantedly.com/companies/sms
͖ΐ͏ͷ
‣ “RailsͷΩϨΠͳઃܭ"࠷ॳ͔Βͯ͢ઃܭ͢Δͷ Ή͔͍ͣ͠ͷͰ෮ͯ͠࡞ΔͱΑͦ͞͏ɻ ‣ ʰॅΈͳ͕Β૿ங͍ͯ͘͠ײ͡ʱ@m_seki https://speakerdeck.com/m_seki/re-iterative-development-iteration-4?slide=57 ‣ Railsʹ͓͍ͯɺͦͷͱ͔͔ͬΓͱͯ͠ϑΥʔϜʹ ண͢Δͷѱ͘ͳͦ͞͏ɻ ͖ΐ͏ͷ
എܠ
‣ DBͷςʔϒϧʹ΄΅Ұகͨ͠ߏͷσʔλ͕POST͞Εͯ ͖ͯɺͦΕΛARͰγϯϓϧʹӬଓԽ͢Δɻ ‣ ͳ͔ͳ͔ͦ͏ߦ͔ͳ͍͜ͱଟ͍ΑͶɻ ૉͳRails͕ఆ͍ͯ͠Δ͜ͱ
‣ Ϣʔβʔ͕ʹ͢Δใ୯Ґ(≒ϑΥʔϜͷߏ)ͱɺਖ਼نԽ ͞ΕͨσʔλߏҟͳΔɻ ‣ DBʹӬଓԽ͢Δ͚ͩͰࡁ·ͳ͍͜ͱ͕͋Δɻ ‣ ϝʔϧΛૹΔɺϩάΛऔΔɺඇಉظδϣϒΛΩοΫ͢Δɺ Πϕϯτͱͯ͠Publish͢ΔɺɺɺͳͲͳͲ “ͦ͏ߦ͔ͳ͍͜ͱ”
ࠩҟΛຒΊΔςΫχοΫ ͏·͘ߦ͖ͦ͏͚ͩͲͬ͘͠Γ͜ͳ͍ͭ
‣ ίϯτϩʔϥʔͰARϞσϧʹ٧Ί͢ɻ ‣ ͍ΘΏΔFat ControllerʹͳΓ͕ͪ ‣ ͷͰϞσϧʹدͤΔɺͱFat Model ‣ ·͍͍͋ͯ͑͠Ϟσϧ͕Ͱ͔͍΄͏͕·ͩϚγ…
ࠩҟΛຒΊΔςΫχοΫ
‣ accept_nested_attributes ͰҰ࿈ͷσʔλΛ ·ͱΊͯೖྗͤ͞Δ ‣ ϑΥʔϜίϯτϩʔϥʹɺӬଓԽͷσʔλάϥϑ͕࿐ग़͢Δ ‣ ͓͢͢Ί͠·ͤΜɻ ࠩҟΛຒΊΔςΫχοΫ
‣ ʮӬଓԽ͢Δ͚ͩʯͰͳ͍ॲཧΛίʔϧόοΫͱ࣮ͯ͠ݱ ͢Δɻ ‣ ίϧόοΫ͍ͨ͠ͱ͖ͱɺ୯ʹσʔλΛอଘ͍ͨ͠ͱ͖ͷหผ͕͍ͨΜ ‣ ίʔϧόοΫʹͨ͘͞Μͷ if ͕Ͱ͖ͯ͘Δͷ͕༧ஹ ࠩҟΛຒΊΔςΫχοΫ
‣ 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 ͍ͨΜͩΑͶɺɺɺͱ͍͏ͷ͕ΒΕ͖ͯͨ
͡Ί͔Β ͪΌΜͱ ઃܭ͢ΔͷΉ͔͍ͣ͠
ܧଓతʹҭͯΔҰา
“ ࠷༗༻ͳઃܭݪଇʹɺϓϩάϥϜʢϢʔ βʔΠϯλʔϑΣΠεʣͷϓϨθϯςʔγϣ ϯͱͦͷଞͷػೳΛ͏·͚͘Δɺͱ͍ ͏ͷ͕͋Γ·͢ɻ ϓϨθϯςʔγϣϯͱυϝΠϯͷ http://bliki-ja.github.io/PresentationDomainSeparation/
‣ Webͷೖྗ = request ʹू͞Ε͍ͯΔσʔλ ‣ ͱͦΕΛಋͨ͘ΊͷϑΥʔϜͦͷଞը໘ ‣ϦϯΫͰͷGETભҠೖྗͱ͍͑ೖྗ͚ͩͲɺ ͜͜Ͱ;Ε·ͤΜɻ ‣ඇಉظδϣϒͰ
AJ#perform ͷҾڥมͳͲ͕ ೖྗͱͳΔɻ RailsͷϓϨθϯςʔγϣϯ
‣ ʮͦͷଞͷػೳʯ ‣ 1ͭҎ্ͷςʔϒϧʹҰ࿈ͷσʔλΛ·ͱΊͯӬଓԽ͢Δ ‣ ࿈ܞγεςϜʹ͚ͯΠϕϯτΛPub͢Δ ‣ ͳͲͳͲ RailsͰ͍͏υϝΠϯ
‣ ϓϨθϯςʔγϣϯͷ͕ࣝɺʮͦͷଞͷػೳʯʹϦʔΫ ͠ͳ͍Α͏ʹɻ·ͣೖྗΛ͖ͬΓͤ͞Δɻ ʮ͏·͘ʯ͚Δ
‣ ίϯτϩʔϥʹͯparams͔ΒΛऔΓग़͠ɺHash จࣈྻͱͯ͠ѻ͏ɻ ‣ ࣮ଶ͕ AC::Parameters Ͱ Hash ͷΑ͏ʹѻ͏ɻ৺ͷͰܕΛݟΔ ‣
HTTP༝དྷͷσʔλɺrequest͔ΒऔΓग़͓ͯ͘͠ɻ ‣ #user_agent ͱ͔ɺΫοΩʔͷͱ͔ ೖྗΛ͖ͬΓ
‣ ొϖʔδͰϝʔϧΞυϨεΛೖྗͤ͞Δɻ ‣ ೖྗ͞ΕͨϝʔϧΞυϨεΛอଘ͢Δ ྫ: Ϣʔβʔొ
‣ ࣮ࡏ֬ೝ༻ͷURLτʔΫϯҰॹʹอଘ͢Δɻ ‣ ͜Ε after create ίʔϧόοΫͰΔ͜ͱଟ͍͠ɺͦΕ͚ͩͳΒ͞΄ͲࠔΒͳ͍͚Ͳɻ ‣ τʔΫϯΛؚΉURLΛϝʔϧͰૹ৴͢Δɻ ‣
͜ΕΛίʔϧόοΫͰΔͱՒࠜʹͳΓ͕ͪɻ ྫ: AR͚ͩͰ·͔ͳ͍ͮΒ͍ʮΔ͜ͱʯ
‣ ίϯτϩʔϥͰऔΓग़ͨͨͪ͠Λೖྗʹ͢Δɻ ‣ ୯Ұͷϝιουݺͼग़͠ͰॲཧҰࣜΛ࣮ߦ͢Δɻ ‣ ໊લΛ͚ͭΔͷ૬มΘΒ͍ͣ͠ ‣ ಈ໊ࢺʹͨ͠Γɺpre/suffix͚ͭͨΓɺͦͷଞنΛಋೖͨ͠Γɻɻɻ ‣ ؤுΕม͑ΒΕΔͷͰɺνʔϜͰͬ͘͠ΓདྷΔͭʹ͢ΔͱΑ͍ɻ
͚ΔͨΊͷΛಋೖ͢Δ(ศ্ٓϑΥʔϜΦϒδΣΫτͱݺͼ·͢)
“ • ಉ͡جຊϓϩάϥϜΛɺॏෳίʔυͳ͠ʹɺෳͷϓϨθϯςʔγϣϯʹ ରԠͤ͞Δ͜ͱ͕Ͱ͖Δ • ϢʔβʔΠϯλʔϑΣΠεςετ͕͠ʹ͍ͨ͘ΊɺͦΕΛ͢Δ͜ͱ ʹΑΓɺςετՄೳͳϩδοΫ෦ʹूதͰ͖Δ • εΫϦϓτ༻ͷ"1*αʔϏεͱͯ͠֎෦Խ͢ΔͨΊͷ"1*ΛָʹՃͰ ͖ΔʢબՄೳͳϓϨθϯςʔγϣϯ෦Ͱݟ͔͚Δʣ
ϓϨθϯςʔγϣϯͱυϝΠϯͷ http://bliki-ja.github.io/PresentationDomainSeparation/
‣ ͜ͷ”͚ΔͨΊͷ”ͷೖྗPOROʹͳΔͷͰɺςε τ͔Β؆୯ʹݺͼग़ͤΔɻ ‣ PORO: Plain Old Ruby Object =
ී௨ͷΦϒδΣΫτ ‣ ؆୯ʹݺͼग़ͤΔͷͰɺଞͷςετͰͷσʔληοτΞο ϓʹ͑Δɻ ςετՄೳ
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Λϝʔϧ͢Δͷͷςετ
͜ͷʮϑΥʔϜΦϒδΣΫτʯΛߋʹɺͨͱ͑͜Μͳ;͏ʹҭͯͨ͘ͳͬͨͱͯ͠: 1. ϑΥʔϜΦϒδΣΫτೖྗϋϯυϦϯάʹͱͲΊɺ ӬଓԽͷͨΊʹαʔϏεΛ͏Ұઃ͚͍ͨɻ 2. ϝʔϧૹ৴ΤϯςΟςΟӬଓԽΛPub/SubͰݕͯ͠ ૄ݁߹ʹ͍ͨ͠ɻ “ϩδοΫ෦ʹूதͰ͖Δ”
> ӬଓԽͷͨΊʹαʔϏεΛઃ͚͍ͨ 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ϨΠϠઃ͚ͯɺϓϨθϯςʔγϣϯͱͷΠϯ λʔϑΣʔεมΘΒͣ҆ఆ͍ͯ͠Δɻ
> Pub/SubͰૄ݁߹ʙ UserRegistrationForm.new(email: email).call + OurJob.execute_all! token =
extract_token_from_sent_email(AM::Base.deliveries.last) ‣ ΠϯλʔϑΣʔε҆ఆͨ͠··ɺΞʔΩςΫνϟมߋʹ ඞཁͳमਖ਼͚ͩΛೖΕΕΑ͍ɻ
‣ ΠϯλʔϑΣʔε͕҆ఆ͢ΔͷͰɺϩδοΫ෦Λ มԽ/ચ࿅͢Δࣗ༝͕ಘΒΕΔɻ ‣ (ಈ࡞͢Δ && !ΩϨΠ) ͳίʔυΛɺ (ಈ࡞͢Δ &&
ΩϨΠ) ͳίʔυʹҭͯΒΕΔɻ ‣ ϦϑΝΫλϦϯά! “ϩδοΫ෦ʹूதͰ͖Δ”
ศ্ٓϑΥʔϜΦϒδΣΫτͱݺΜͩ ҙਤ
‣ A: ͲͬͪͰ͍͍ ‣ ࣗಈςετ͕͋ͬͯϦϑΝΫλϦϯά͘͢͠ͳ͍ͬͯΕokɻ ‣ ʮೖྗΛͱΓ·ͱΊͯόϦσʔγϣϯ·ͰΛ͢Δʯͱɺ ʮͦͷvalidͳೖྗͰॲཧΛ͢Δʯʹׂ͍͍ͯ͠Μ͡Όͳ͍͔ͳɻ ‣ ࠷ॳʹখ͘͞࡞Δͱ͖UIͱ͚ۙͮͨ΄͏͕͍͍Μ͡Όͳ͍͔ͳ
‣ ʮϑΥʔϜʯͬͯͭ·ΓɺαʔϏεΛఏڙ͢Δଆ͕ར༻ऀʹظ͢Δ ߦಈͦͷͷͩΑͶɻ ‣ ͦ͜ʹԊͬͨͷΛ࡞Δͷ͕ૉ͡Όͳ͍͔ͳɻ αʔϏεϨΠϠ͡Όͳͯ͘ϑΥʔϜΦϒδΣΫτਪ͠ͳͷͳͥ?
‣ ʮೖྗʯͱʮϩδοΫ෦ʯΛ͚Α͏ ‣ ϓϩμΫτίʔυςετεοΩϦ͢Δͣ! ‣ ࠷ॳখ͘͞φΠʔϒʹ࡞Ζ͏ ‣ ઃܭ͕ΜΓ͗ͯ͢ർΕͳ͍Α͏ʹ… ‣ Ͳ͏͍͏நԽ͕ྑ͍ͷ͔ɺ࠷ॳΘ͔Βͳ͍͔ΒͶ
‣ ͪΌΜͱʑϦϑΝΫλϦϯά͠Α͏ ‣ φΠʔϒͳ··ΰνϟοͱੵΈଓ͚ΔͱͦΕμϝͰ͢Ͷ ͲͬͪͰΑ͘ͳ͍͜ͱ
·ͱΊ
‣ Ϗϡʔ / ίϯτϩʔϥ / AR::B ͷࡾ૬ߏͰ·͔ͳ͑ͳͦ͏ ͳ߹ɺബ͍Λ͏Ұ࡞ͬͯΈΔͱΑ͍ɻ ‣ ίϯτϩʔϥ͕ѻ͏WebͷೖྗͱɺϩδοΫʹඞཁͳ
ೖྗͷڥքͱͳΔ͜ͱΛҙࣝ͢Δɻ ‣ φΠʔϒ͔ͭςετ͕ॻ͖͍͢ϨΠϠ͔Β͡Ίͯɺ ෮͠ͳ͕ΒมԽ͍͚ͯ͠ΔΑ͏ʹ! ·ͱΊ