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 の `build_xxx` / The Hard Facts of `...
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
megane42
July 30, 2019
Programming
290
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
本当は怖い Rails の `build_xxx` / The Hard Facts of `build_xxx` of Rails
megane42
July 30, 2019
More Decks by megane42
See All by megane42
Immutable ActiveRecord
megane42
0
350
Rails deprecation warning に立ち向かう技術 / v.s. rails deprecation warnings
megane42
0
790
OSS コミットゴルフのすすめ / Let's play OSS-contribute-golf
megane42
0
130
ゆる計算理論ラジオ / P vs NP for beginner
megane42
1
270
How to Make "DJ giftee"
megane42
1
1k
Rails 6 Upgrade "Practical" Guide
megane42
6
1.4k
updated_at に依存したら大変なことになった / Don't depend on updated_at
megane42
0
630
Other Decks in Programming
See All in Programming
Agentic UI
manfredsteyer
PRO
0
180
Developing with AI Agents — Codex, Claude Code & Cowork Practical Guide
x5gtrn
PRO
0
1.3k
メソッドのジェネリクスでGoの夢は広がるか? / Kyoto.go #65
utgwkk
3
850
過去最大のMCPアップデート! 2026-07-28 RC版の謎に迫る
licux
6
370
Contextとはなにか
chiroruxx
1
330
Composerを使ったサプライチェーン攻撃の様子を眺めてみる #phpstudy
o0h
PRO
2
250
1B+ /day規模のログを管理する技術
broadleaf
0
100
AI 時代のソフトウェア設計の学び方
masuda220
PRO
29
13k
並列実装の現場、2ヶ月間実務でAIを使い倒したAIもPCも私も限界が近い
ming_ayami
0
130
ローカルLLMでどこまでコードが書けるか -拡張版 / How much code can be written on a local LLM Extended
kishida
11
4.3k
Dataformのリポジトリを立ち上げるときにまずやること / dataform-day0-2026
snhryt
0
170
The ROI of Quarkus for Spring Boot Applications
hollycummins
0
120
Featured
See All Featured
Accessibility Awareness
sabderemane
1
140
4 Signs Your Business is Dying
shpigford
187
22k
Google's AI Overviews - The New Search
badams
0
1k
So, you think you're a good person
axbom
PRO
2
2.1k
Why Mistakes Are the Best Teachers: Turning Failure into a Pathway for Growth
auna
0
160
Why Our Code Smells
bkeepers
PRO
340
58k
Breaking role norms: Why Content Design is so much more than writing copy - Taylor Woolridge
uxyall
0
320
SEO for Brand Visibility & Recognition
aleyda
0
4.6k
Thoughts on Productivity
jonyablonski
76
5.2k
Exploring the relationship between traditional SERPs and Gen AI search
raygrieselhuber
PRO
2
4k
New Earth Scene 8
popppiees
3
2.3k
AI in Enterprises - Java and Open Source to the Rescue
ivargrimstad
0
1.3k
Transcript
本当は怖い Rails の build_xxx @ giftee tech bash #2 (2019‑07‑30)
kazama (@megane42) Solution dev. GCP
概要 Rails の build_xxx 系のメソッドが怖かったという話をします
今日の登場人物(モデル) User Blog user has_one blog
お題 ある user の持ち物としての blog インスタンスを作りたい
方法 create_xxx インスタンスを作って DB に即保存 user.create_blog(title: "foo", ...) build_xxx インスタンスは作るけど
DB に保存はしない 今日の主役 user.build_blog(title: "foo", ...)
疑問 has_one だけど何度も繰り返したらどうなるの?
create の場合 まず新しい blog レコードを保存 次に古い blog レコードの外部キー (user_id) を
null にする dependent: :destroy のときはここが DELETE になる 結果的に子レコードは 1 つに保たれるので、まあわかる # 2 回目の user.create_blog を実行したときの SQL begin transaction INSERT INTO "blogs" ("user_id", "created_at", "updated_at" commit transaction begin transaction UPDATE "blogs" SET "user_id" = ?, "updated_at" = ? WHERE commit transaction
build の場合 # 1 回目 blog = user.build_blog blog.save #
2 回目 blog = user.build_blog さて何が起きるでしょう?
None
結果 まさかの 更新系 が走る dependent: :destroy の場合は DELETE が走る! このあと結局
blog.save をしなかった場合 or 失敗した場合、当 然旧レコードは更新されっぱなしのまま build_xxx は DB を更新しない、という直感に反している # 2 回目の blog = user.build_blog を実行したときの SQL begin transaction UPDATE "blogs" SET "user_id" = ?, "updated_at" = ? WHERE commit transaction
対策 new を使う build_xxx まで含めてトランザクションを張る build_xxx が更新系を実行しうる、という認識を持っておく transaction do blog
= user.build_blog blog.some_operation blog.save end
余談 : ドキュメントにはどう書いてある? Account#build_beneficiary (similar to Beneficiary.new(account_id: id) ) シミラートゥー(イコールとは言ってない)
https://api.rubyonrails.org/classes/ActiveRecord/Associations/Cla ssMethods.html#method‑i‑has_one
余談 : create_xxx も怖くね? なぜか トランザクションが分かれている INSERT 後の UPDATE or
DELETE に失敗するとゴミレコードが残る 例えば belongs_to: に optional: true を付け忘れると UPDATE に失敗する これもトランザクション張った方がいいのかも? # 2 回目の user.create_blog を実行したときの SQL (再掲) begin transaction INSERT INTO "blogs" ("user_id", "created_at", "updated_at" commit transaction begin transaction UPDATE "blogs" SET "user_id" = ?, "updated_at" = ? WHERE commit transaction
まとめ build_xxx は 更新系 を発行しうる create_xxx も怖かった