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
実践 Rails アソシエーションリファクタリング / Rails association r...
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Kei Shiratsuchi
PRO
October 22, 2022
Technology
9.9k
8
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
実践 Rails アソシエーションリファクタリング / Rails association refactoring in practice
Kaigi on Rails 2022
https://kaigionrails.org/2022/
https://kaigionrails.org/2022/talks/kei-s/
Kei Shiratsuchi
PRO
October 22, 2022
More Decks by Kei Shiratsuchi
See All by Kei Shiratsuchi
モノリスとマイクロサービスの橋渡し - ベターからモアベターへ
kei_s
PRO
0
130
なぜ リアーキテクティング専任チームを作ったのか
kei_s
PRO
2
1.7k
「Go言語でつくるインタプリタ」を Rust で移植してみた / "Write An Interpreter In Go" In Rust
kei_s
PRO
1
2.1k
Rust言語で作るインタプリタ / Write An Interpreter In Rust
kei_s
PRO
2
810
育児休業のご報告と、育児グッズとしてのスマートスピーカー / Parental Leave and SmartSpeaker
kei_s
PRO
0
900
「深層学習による自然言語処理」読書会 第6章2.7
kei_s
PRO
0
490
「深層学習による自然言語処理」読書会 第5章5.1
kei_s
PRO
0
500
最近個人的に気になるプログラミング言語おさらい Ruby, Python, Go, Rust, Julia
kei_s
PRO
0
1.1k
「深層学習による自然言語処理」読書会 第2章2.1~2.5
kei_s
PRO
0
500
Other Decks in Technology
See All in Technology
ACE-Step-1.5で見る 音楽生成AIのしくみと“破綻だけ直す”Retake機能の開発【zennfes spring 2026 登壇資料】
personabb
1
200
連合学習と機密コンピューティング
lycorptech_jp
PRO
0
110
自宅LLMの話
jacopen
1
500
2026 TECHFRESH 畢業分享會 - AI-Native 重塑軟體工程與虛擬講師
line_developers_tw
PRO
0
920
Building applications in the Gemini API family.
line_developers_tw
PRO
0
3.2k
SIer20年! 培ったスキルがスタートアップで輝く時
shucho0103
0
850
Claude Code の Sandbox 機能を Anthropic Sandbox Runtime(srt) で試そう!/lets-play-anthropic-sandbox-runtime
tomoki10
1
560
非定型業務をAI slackbotで自動化する ~ 社内要望を自動壁打ちするbotを作った ~/automating-ad-hoc-work-with-ai-slackbot
shibayu36
0
640
小さく始める AI 活用推進 ― 日経電子版 Web チームの事例/nikkei-tech-talk47
nikkei_engineer_recruiting
0
250
白金鉱業Meetup_Vol.24_「AIエージェントは分けるほど良い」は本当か? / Is it true that “the more you divide AI agents, the better”?
brainpadpr
1
350
「エンジニア進化論」2028年の開発完全自動化、エンジニアはどう進化するか
cyberagentdevelopers
PRO
6
4.9k
AGENTS.mdとSkillsで始めるAIエージェント活用
sonoda_mj
3
200
Featured
See All Featured
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
22k
Game over? The fight for quality and originality in the time of robots
wayneb77
1
200
B2B Lead Gen: Tactics, Traps & Triumph
marketingsoph
0
140
We Have a Design System, Now What?
morganepeng
55
8.2k
職位にかかわらず全員がリーダーシップを発揮するチーム作り / Building a team where everyone can demonstrate leadership regardless of position
madoxten
62
54k
How GitHub (no longer) Works
holman
316
150k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
28
3.5k
Max Prin - Stacking Signals: How International SEO Comes Together (And Falls Apart)
techseoconnect
PRO
0
180
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
234
17k
HDC tutorial
michielstock
2
710
Ethics towards AI in product and experience design
skipperchong
2
310
VelocityConf: Rendering Performance Case Studies
addyosmani
333
25k
Transcript
࣮ફ Rails ΞιγΤʔγϣϯ ϦϑΝΫλϦϯά നܛ, Kei Shiratsuchi, @kei_s Kaigi on
Rails 2022, 2022.10.22(Sat)
Πϯτϩ • Day 1 ͷ @pndcat ͞ΜʹΑΔʰཏສʹʮ͍͍Ͷʯ͢ΔͨΊͷ σʔλߏ ʱͷɺٯํͷϦϑΝΫλϦϯάͷΛ͠·͢ •
ϙϦϞʔϑΟοΫؔ࿈Λதؒςʔϒϧ • ͲͪΒɺཧ༝͕͋ͬͯҙຯ͕͋Δɺͱ͍͏͜ͱΛ࣋ͬͯ ؼ͍͚ͬͯͨͩΕ 🙏 • ͲͪΒ࠾༻͍͍ͯͨͩͨ͠ Kaigi on Rails νʔϜ͍͢͝ 👏
ࣗݾհ • നɹܛʢγϥπνɹέΠʣ • : kei-s, : @kei_s • ANDPAD
גࣜձࣾ Tech Lead • ॳΊͯ rails new ͔ͯ͠Β 15 ͘Β͍ • ࠓ Kaigi on Rails ͷୗࣇαϙʔτΛར༻ͤͯ͞Β͍ͬͯ·͢ • ͱͯྑ͍औΓΈͰײँ͍ͯ͠·͢ʂ
എܠ
લఏ • ANDPAD : ݐஙɺݐઃۀ͚ͷ SaaS • த৺ͱͳΔҰͭͷ Rails ΞϓϦͰɺෳͷۀυϝΠϯͷόο
ΫΤϯυΛఏڙ͍ͯ͠Δ • ࢪཧɺݕࠪɺνϟοτɺetc… • ͦΕͧΕͷυϝΠϯʹ։ൃνʔϜ͕͋Δ • ͦΕΒͷνʔϜ͕Ұͭͷ Rails ΞϓϦʹରͯ͠ػೳ։ൃͯ͠ ͍Δ
എܠ • ෳͷυϝΠϯͷػೳ͕૬Γ͍ͯ͠ΔͨΊɺRails ΞϓϦ͔ͳΓେنʹͳͬ ͍ͯΔ • Day 1 ͷ makicamel
͞ΜͷൃදΛࢀর͍ͩ͘͞ • ͜ͷ Rails ΞϓϦͰɺϙϦϞʔϑΟοΫؔ࿈͕ଟ༻͞Ε͍ͯΔ • ಛʹʮࣸਅʯʮࢿྉʯͳͲɺ͍ΘΏΔετοΫσʔλͷؔ࿈͚ʹ༻͍Β Ε͍ͯΔ • ͜ΕΒͷσʔλɺυϝΠϯΛލ͍Ͱར༻͞Ε͍ͯΔ • ͋ΔυϝΠϯͰ࡞͞ΕͨσʔλΛɺผͷυϝΠϯ͔ΒࢀরͰ͖Δ • ྫɿࢪཧͰΞοϓϩʔυͨࣸ͠ਅΛɺνϟοτʹషΓ͚Δ
ϙϦϞʔϑΟοΫؔ࿈ͱ • ҰͭͷϞσϧΛෳͷϞσϧʹඥ͚ͮΔ • *_type ΧϥϜʹϞσϧͷΫϥε໊Λ อଘ͢Δ • ར: ͋ΒΏΔϞσϧʹඥ͚ͮΔ͜ͱ͕
Ͱ͖Δ • ઃܭ࣌ʹଘࡏ͠ͳ͔ͬͨϞσϧͱ ඥ͚ͮΒΕΔ • ܽ: DBͰ֎෦ΩʔΛઃఆͰ͖ͳ͍ class Picture < ApplicationRecord belongs_to :imageable, polymorphic: true end class Employee < ApplicationRecord has_many :pictures, as: :imageable end class Product < ApplicationRecord has_many :pictures, as: :imageable end @employee.pictures # = > [#<Picture: . . >, . . ] @product.pictures # = > [#<Picture: . . >, . . ]
Ұ൪ͷͭΒΈ • σʔλϞσϧͷॴ༗ʹϙϦϞʔϑΟο Ϋؔ࿈ • σʔλϞσϧͷࢀরʹϙϦϞʔϑΟο Ϋؔ࿈ • ສͱສΛؔ࿈ͤ͞Δ͜ͱ͕Ͱ͖ ͯศརʢຊʹ…???ʣ
• ࣮ࡍʹɺॴ༗ͱࢀরͰ͍͚Δϝ Ϧοτ͕ͳ͍ ॴ༗ ࢀর
Կ͕ى͖͍͔ͯͨ • ؔ࿈͚ͷશ༰Ѳ͕͍͠ • σʔλΛͲ͔͜Βར༻͍ͯ͠Δ͔͕໌ࣔతͰͳ͍ • σʔλϞσϧଆʹఆ͕ٛͳ͘ɺಈ࡞ͷதͰ͔͠ݱΕͳ͍ • σʔλΛར༻͢Δ৽ػೳͰɺ࠷దͳ࣮͕Θ͔Βͳ͍ͨ Ίطଘ࣮Λ౿ऻ͠ɺෳࡶ͕͞૿େ͍ͯ͘͠
• υϝΠϯΛލ͍Ͱར༻͞Ε͍ͯΔͨΊมߋͷӨڹൣғ͕େ ͖͘ɺ֤υϝΠϯͷ։ൃνʔϜͰमਖ਼͕͍͠
ਅͷ՝ • কདྷతʹɺେنRailsΞϓϦΛ υϝΠϯ͝ͱʹղମ͍͖͍ͯͨ͠ • ۩ମతͳಓے To Be Determined
• υϝΠϯΛލ͍ͰΘΕΔσʔλ ͷѻ͍ඞͣ՝ʹͳΔ • શ༰͕ѲͰ͖ͳ͍ෳࡶͳ࣮Λ ղফ͢Δඞཁ͕͋Δ Rails ΞϓϦ ࢪཧ νϟοτ ࣸਅ Ϟσϧ Ϟσϧ ϚΠΫϩαʔϏεʁ ϞδϡϥϞϊϦεʁ
ϦϑΝΫλϦϯάํ • ϙϦϞʔϑΟοΫؔ࿈Λɺதؒ ςʔϒϧʹΑΔؔ࿈͚ʹஔ͖ ͑Δ • ؔ࿈͚Λ໌ࣔͰ͖Δ • ॻ੶ʮSQLΞϯνύλʔϯʯͰ հ͞Ε͍ͯΔख๏
class Photo < ApplicationRecord has_many :message_photos has_many :messages, through: :message_photos end class MessagePhoto < ApplicationRecord belongs_to :message belongs_to :photo end class Message < ApplicationRecord has_many :message_photos has_many :photos, through: :message_photos end
େنΞϓϦͳΒͰͷ • ϝϯςφϯελΠϜΛઃ͚ͣʹਐΊ͍ͨ • มߋՕॴ͕ଟ͍ͨΊɺఀΊΔͷඇݱ࣮త • Ҡߦதʹෆ۩߹͕ൃ֮ͨ͠ΒΓ͍ͨ͠͠ • ҠߦՕॴ͕ཏ͠Ε͍ͯΔ͔ෆ҆ •
ࣗಈςετͰΧόʔͰ͖͍ͯͳ͍Օॴ͕͋ΔͷͰ ͳ͍͔
ϦϑΝΫλϦϯάͷ࣮ࢪ
ҠߦܭըͰॏࢹ͢ΔϙΠϯτ • ແఀࢭͰߦ͏ • ՄೳͳݶΓ҆શʹߦ͏ • ͙͢ʹΓ͕͠Ͱ͖ΔΑ͏ʹ͢Δ • → ৽چΞιγΤʔγϣϯͷಉ࣌ॻ͖ࠐΈ
• Ҡߦ͖͠Δ • Ҡߦ࿙ΕΛ์ஔ͠ͳ͍͜ͱ • → ϓϩμΫγϣϯڥͰൈ͚࿙Ε͕ͳ͍͔ݕ
ҠߦͷྲྀΕ • 4ճͷϦϦʔε🚀ɺ2ճͷσʔλमਖ਼📝Λߦ͏ 1. 🚀 ҠߦઌϞσϧ࡞ɺچˠ৽ͷಉ࣌ॻ͖ࠐΈ 2. 📝 طଘσʔλΛ৽ΞιγΤʔγϣϯʹొ 3.
🚀 ৽ΞιγΤʔγϣϯʹஔ͖͑ɺ৽ˠچͷಉ࣌ॻ͖ࠐΈ 4. 🚀 ൈ͚࿙Εݕ 5. 🚀 ্͛ 6. 📝 چσʔλΛআ
1. 🚀 ҠߦઌϞσϧ࡞ɺچˠ৽ͷಉ࣌ॻ͖ࠐΈ • ҠߦઌͱͳΔதؒςʔϒϧΛ࡞͢Δ • ৽ΞιγΤʔγϣϯΛɺچΞιγΤʔγϣϯͱผ໊Ͱੜ͢ • after_create ίʔϧόοΫͰɺچΞιγΤʔγϣϯ͕࡞͞ΕͨΒ৽ΞιγΤʔ
γϣϯΛಉ࣌ʹ࡞͢Δ • ඞཁʹΑͬͯɺߋ৽ɾআ͞ΕΔ߹ରԠ • 👉 ͜Ε͔ΒՃ͞ΕΔσʔλ৽چͰಉظ͞ΕΔ class Message < ApplicationRecord has_many :photos, as: :imageable has_many :message_photos has_many :renewed_photos, through: :message_photos, source: :photo end class Photo < ApplicationRecord belongs_to :imageable, polymorphic: true has_many :message_photos has_many :messages, through: :message_photos after_create :create_message_photos!, if: - > { imageable.is_a?(Message) } def create_message_photos! message_photos.create!(message: imageable) end end
2. 📝 طଘσʔλΛ৽ΞιγΤʔγϣϯʹొ • چΞιγΤʔγϣϯʹΑΔطଘσʔλΛಡΈग़͠ɺ৽ ΞιγΤʔγϣϯʹొ͢ΔόονॲཧΛ࣮ߦ͢Δ • 👉 શͯͷσʔλ͕৽چͰಉظ͞ΕΔ
3. 🚀 ৽ΞιγΤʔγϣϯʹஔ͖͑ɺ৽ˠچͷಉ࣌ॻ͖ࠐΈ • ผ໊Ͱ࡞ͨ͠৽ΞιγΤʔγϣϯΛར༻͢ΔΑ͏मਖ਼͢Δ • ৽ΞιγΤʔγϣϯΛͬͯɺγϯϓϧͳ࣮Λ͢Δ • ࡞ɾߋ৽ՕॴϑΟʔνϟʔτάϧͰΓͤΔΑ͏ʹ͢Δ •
৽ˠچͷಉ࣌ॻ͖ࠐΈΛ࣮͢Δ • ࡞࣌ʹ *_type ͱ *_id ΛదʹຒΊΔ • چˠ৽ͷಉ࣌ॻ͖ࠐΈఀࢭͤͣҡ࣋͢Δ • ஔ͖͑ʹൈ͚͕͋ͬͨ߹Γͨ͠͠߹ʹ͕ى͖ͳ͍Α͏ʹ • 👉 ·ͩɺશͯͷσʔλ͕৽چͰಉظ͞ΕΔ
4. 🚀 ൈ͚࿙Εݕ • چΞιγΤʔγϣϯ͕ར༻͞ΕͨΒɺϩάΛग़ྗͤ͞Δ • extend: Φϓγϣϯʹϩά༻ϞδϡʔϧΛ͠ɺϞδϡʔϧͷ self.extended ͕ൃ
Րͨ͠ΒɺͲ͔͜ͰΠϯελϯεԽ͞Εͨͣ • ϩάʹ backtrace Λग़͠ɺͲ͔͜ΒݺΕ͔ͨΛௐࠪ͢Δ • 👉 ϓϩμΫγϣϯͰϩά͕ग़Δ͔Ұఆظ༷ؒࢠΛݟΔ class Message < ApplicationRecord has_many :photos, as: :imageable, extend: LoggingLeakage end module LoggingLeakage def self.extended(obj) # ผʑͷ obj Ͱ3ճݺͼग़͞ΕΔͨΊɺҰ͚࣮ͩߦ͞ΕΔΑ͏ʹ͢Δ return if obj.class.to_s ! = 'Photo : : ActiveRecord_Associations_CollectionProxy' backtrace = caller.grep(/ # { Regexp.escape(Rails.root.to_s)}/) leakage_logger.info "Replace leakage detected. # { backtrace}" end end
5. 🚀 ্͛ • چΞιγΤʔγϣϯΛআ • ৽ΞιγΤʔγϣϯΛผ໊͔Βຊདྷͷ໊લʹมߋ • ৽ˠچͷಉ࣌ॻ͖ࠐΈͷఀࢭ •
👉 ظ͢ΔίʔυͰͷಈ࡞͕։࢝
6. 📝 چσʔλΛআ • ϙϦϞʔϑΟοΫؔ࿈༻ͷΧϥϜʢ*_type, *_idʣΛ null Ͱ ຒΊΔ •
ରԠ͕ྃͨ͜͠ͱΛࣔͨ͢Ί • 👉 Ҡߦྃʂ
Ͳ͏࣮ͬͯࢪ͍ͯ͠Δ͔
ઐνʔϜ • ϦΞʔΩςΫςΟϯάνʔϜͱ໋໊͞Ε ͨɺυϝΠϯΛԣஅ͢ΔՕॴͷվળΛߦ ͏νʔϜ • طଘͷΈͷͭΒ͍෦Λղফ͠ɺ ͓खຊͱͳΔΑ͏ͳͷΛ࡞Δ • ։ൃνʔϜશମͰɺվળ׆ಈΛܧଓ͠
ͯΔͧɺͱ͍͏จԽΛৢ͍ͨ͠ • ·ͣσʔλϞσϧपΓͷΞιγΤʔ γϣϯվળʹணख Rails ΞϓϦ ࢪཧ νϟοτ ࣸਅ Ϟσϧ Ϟσϧ
εύΠΫίʔυͷॏཁੑ • ࣮ࡍʹҠߦΛ࢝ΊΔલʹɺҠߦεςοϓͷશͯΛ࣮ͯ͠ΈΔ • ࣮ࣺͯͯྑ͍ • ·Ͱͷෆ֬ఆཁૉΛશͯ௵͓ͯ͘͠ • ໎͏ͱ͜ΖΛϖΞϓϩͳͲͰղܾ͢Δ •
ʮௐࠪʯͱʮ࣮ࢪʯͰϑΣʔζΛ͚Δ • εύΠΫ࡞ۀͷݟੵΓ͍͕͠ɺ࣮ࡍͷҠߦ࡞ۀݟੵΓ͕͠ ͍͢ • ʮ࣮ࢪʯظؒதʹɺผՕॴͷʮௐࠪʯΛฒߦͰ͖Δ
ࡉ͔ͳ Tipsʢ࣌ؒతʹׂѪʣ • ΞιγΤʔγϣϯʹ dependent: :destroy ͕͋Δ߹ɺಈ࡞͕มΘΔ • ϙϦϞʔϑΟοΫؔ࿈ͰࢠϞσϧআ͞ΕΔ͕ɺதؒςʔϒϧؔ࿈Ͱ ɺதؒཁૉϞσϧͷΈআ͞ΕΔ
• callback ͳͲͰࢠϞσϧআ͢ΔΑ͏ʹ͢Δ • چˠ৽ͱ৽ˠچͷಉ࣌ॻ͖ࠐΈ͕྆ํଘࡏ͢ΔλΠϛϯά͕͋ΔͨΊɺೋॏʹ ൃՐ͢ΔͷΛճආ͢Δ • อଘ࣌ʹ :skip_double_write ͷΑ͏ͳ attribute Λੜ੍ͯ͠ޚ͢Δ • ൈ͚࿙Εݕͷϩάಉ͡ՕॴͰଟྔʹग़ΔՄೳੑ͕͋ΔͨΊɺ1ϦΫΤετͰ ॏෳ͢ΔϩάΛ uniq ͢ΔػߏΛࠐΉ
·ͱΊ • σʔλϞσϧઃܭΛஔ͖͑Δͷ݁ߏେม • ՄೳͳݶΓϦϦʔεલʹݕ౼͠Α͏…! • ͱ͍͑ɺॳఆͱมΘΔ͜ͱ͋ΓಘΔ • ෳࡶͰྑ͘ͳ͍෦ɺ์ஔ͍ͯ͠Δͱ૿͑Δ •
ෳࡶͰ͍͔͠Βͦ͜ɺલྫΛ౿ऻͯ͠͠·͏ • ϦϑΝΫλϦϯάʹΑͬͯʮՁΛఏڙ͠ଓ͚Δʯʹد༩͢Δ • ʮ͠ଓ͚ΔʯͨΊʹɺ͔Γ͘͢ɺखΛೖΕ͘͢อͭ