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
ActiveRecord Anti-Patterns
Search
Ethan Gunderson
November 04, 2011
Technology
2
310
ActiveRecord Anti-Patterns
Ethan Gunderson
November 04, 2011
Tweet
Share
Other Decks in Technology
See All in Technology
KotlinConf 2025_イベントレポート
sony
1
140
DDD集約とサービスコンテキスト境界との関係性
pandayumi
3
290
Firestore → Spanner 移行 を成功させた段階的移行プロセス
athug
1
490
大「個人開発サービス」時代に僕たちはどう生きるか
sotarok
20
10k
バイブスに「型」を!Kent Beckに学ぶ、AI時代のテスト駆動開発
amixedcolor
2
580
AI開発ツールCreateがAnythingになったよ
tendasato
0
130
企業の生成AIガバナンスにおけるエージェントとセキュリティ
lycorptech_jp
PRO
2
190
「Linux」という言葉が指すもの
sat
PRO
4
140
フルカイテン株式会社 エンジニア向け採用資料
fullkaiten
0
8.8k
複数サービスを支えるマルチテナント型Batch MLプラットフォーム
lycorptech_jp
PRO
1
820
TS-S205_昨年対比2倍以上の機能追加を実現するデータ基盤プロジェクトでのAI活用について
kaz3284
1
210
実践!カスタムインストラクション&スラッシュコマンド
puku0x
0
480
Featured
See All Featured
How STYLIGHT went responsive
nonsquared
100
5.8k
Faster Mobile Websites
deanohume
309
31k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
15
1.7k
Raft: Consensus for Rubyists
vanstee
140
7.1k
Fantastic passwords and where to find them - at NoRuKo
philnash
52
3.4k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
48
9.7k
Writing Fast Ruby
sferik
628
62k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
507
140k
[RailsConf 2023] Rails as a piece of cake
palkan
57
5.8k
Measuring & Analyzing Core Web Vitals
bluesmoon
9
580
Build your cross-platform service in a week with App Engine
jlugia
231
18k
Stop Working from a Prison Cell
hatefulcrawdad
271
21k
Transcript
Anti-Patterns for fun and profit Active Record Friday, November 4,
2011
Ethan Gunderson @ethangunderson Friday, November 4, 2011
Friday, November 4, 2011
20% 80% Friday, November 4, 2011
Order.all.slice(0, N).select{ |order| order.status == ‘open’} Friday, November 4, 2011
Common Mistakes Friday, November 4, 2011
ActiveRecord Safari Friday, November 4, 2011
“All non-trivial abstractions, to some degree, are leaky.” - Joel
Spolsky Friday, November 4, 2011
Order.all.slice(0, N).select{ |order| order.status == ‘open’} Friday, November 4, 2011
class Order < ActiveRecord::Base scope :open, where(:status => ‘open’) end
Order.open.limit(5) Friday, November 4, 2011
change_table(:users) do |table| table.string :email table.string :status end Migrations Friday,
November 4, 2011
1. Write lock the table. 2. Make a copy of
the table. 3. Make changes to the copy. 4. Promote copy to primary. 5. Repeat 1-4. Friday, November 4, 2011
connection.execute(“ALTER TABLE `users` ADD COLUMN email varchar(255) DEFAULT NULL, ADD
COLUMN status varchar(10) DEFAULT NULL”) Friday, November 4, 2011
change_table(:users, :bulk => true) do |table| table.string :email table.string :status
end Friday, November 4, 2011
The Leaks, they add up. Friday, November 4, 2011
Not Optimizing Queries Friday, November 4, 2011
Order.all.each do |order| #something end Friday, November 4, 2011
Order.all.each do |order| #something end Ouch Friday, November 4, 2011
Iterate over the DB cursor and construct an array of
rows. Initiate an array of ActiveRecord objects. Friday, November 4, 2011
Order.find_each do |order| #something end Friday, November 4, 2011
Order.find_in_batches do |orders| #something end Friday, November 4, 2011
N + 1 Order.all.each do |order| order.user.first_name end Friday, November
4, 2011
N*OMG Order.all.each do |order| order.user.first_name order.user.address.street ... end Friday, November
4, 2011
1 Order.all.includes(:user).each do |order| order.user.first_name end Friday, November 4, 2011
Order.all.includes(:user => :address) each do |order| order.user.first_name order.user.address.street ... end
Friday, November 4, 2011
https://github.com/nesquena/ query_reviewer Friday, November 4, 2011
if Object.const_defined?('ActiveRecord') ActiveRecord::Base.logger = Logger.new (STDOUT) end In your ~/.irbrc...
Friday, November 4, 2011
Race Conditions Friday, November 4, 2011
validates_uniqueness_of Friday, November 4, 2011
Works. Until you hit production. Friday, November 4, 2011
User 1 Checks for uniqueness User 2 Friday, November 4,
2011
User 1 Checks for uniqueness User 2 Checks for uniqueness
Friday, November 4, 2011
User 1 Inserts record User 2 Inserts record Checks for
uniqueness Checks for uniqueness Friday, November 4, 2011
Success! Friday, November 4, 2011
Success! Danger! Friday, November 4, 2011
create_index :users, :email, :unique => true Friday, November 4, 2011
github.com/trptcolin/consistency_fail Friday, November 4, 2011
Abusive Callbacks Friday, November 4, 2011
Loading Associations Friday, November 4, 2011
class Order < ActiveRecord::Base validate :validate_cc_record def validate_cc_record cc.user !=
user end end Friday, November 4, 2011
Take advantage of dirty attributes Friday, November 4, 2011
class Order < ActiveRecord::Base validate :validate_cc_record def validate_cc_record return unless
cc_id.changed? cc.user != user end end Friday, November 4, 2011
class Order < ActiveRecord::Base before_save :update_item_count def update_sold_count item.increment_sold_count(1) end
end Friday, November 4, 2011
This is slow Friday, November 4, 2011
This is *really* hard to debug in a large application.
Friday, November 4, 2011
Order Item Vendor Sales Friday, November 4, 2011
Order Item Vendor Sales Save fails, returns false Friday, November
4, 2011
Order Item Vendor Sales Save fails, returns false Friday, November
4, 2011
Keep callbacks simple. Friday, November 4, 2011
Breaking the Law Friday, November 4, 2011
Demeter Friday, November 4, 2011
Each unit should have only limited knowledge about other units:
only units "closely" related to the current unit. Each unit should only talk to its friends; don't talk to strangers. Only talk to your immediate friends. Friday, November 4, 2011
You can play with yourself. You can play with your
toys. You can play with toys given to you. You can play with toys you’ve made yourself. http://c2.com/cgi/wiki?LawOfDemeter Friday, November 4, 2011
order.user.address Friday, November 4, 2011
But why do I care? Friday, November 4, 2011
Coupling Friday, November 4, 2011
0 25 50 75 100 Coupling Cost of Change Friday,
November 4, 2011
order.user.address Friday, November 4, 2011
class Order < ActiveRecord::Base delegate :address, :to => :user, :prefix
=> true, :allow_nil => true end Friday, November 4, 2011
order.user_address Friday, November 4, 2011
class Order < ActiveRecord::Base def user_address #different implementation end end
Friday, November 4, 2011
Recap Friday, November 4, 2011
Pay attention to the abstraction Friday, November 4, 2011
Optimize those queries Friday, November 4, 2011
Avoid complicated callbacks Friday, November 4, 2011
Itʼs the law. Follow it. Friday, November 4, 2011
The database is your friend. Friday, November 4, 2011
YMMV Friday, November 4, 2011
Thanks! Friday, November 4, 2011