Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
ActiveRecord Anti-Patterns
Search
Ethan Gunderson
November 04, 2011
Technology
320
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
ActiveRecord Anti-Patterns
Ethan Gunderson
November 04, 2011
Other Decks in Technology
See All in Technology
USB PDを使ってスマホを労わりたい
raspython3
0
180
PHPカンファレンス関西の招待状 / Invitation to PHP Conference Kansai
ykanoh
0
130
分析AIエージェントを育てる、動く環境を育てる
codatum
1
1.1k
re:Invent初参加で変わったこと、2回目にやってみたいこと(JAWS-UG彩の国埼玉 #12)
mhrtech
2
230
Post AI時代のリファクタリング実践記 / Refactoring in the post AI era
kaminashi
1
240
Conditional PED-ANOVA: Hyperparameter Importance in Hierarchical & Dynamic Search Spaces
pfn
PRO
0
140
しろおびから始める!ログ活用の第一歩
shumei_ito
0
950
ソフトウェア ファクトリー - 再現性のあるソフトウェアの工場づくり / Software factory
iktakahiro
6
5k
パスキーの自動テストはどこまでいけるのか
teamlab
PRO
0
250
オントロジーって 結局なにもの? AI エージェントに「意味」を渡す知識設計の話
greenmidori
0
210
古い指輪から広がった JAVA コミュニティ とのつながり
yamad
0
110
SAENM ~Jupyterで残すPoCの試行錯誤、未来の自分と仲間を助ける記録!~
terapyon
0
110
Featured
See All Featured
The B2B funnel & how to create a winning content strategy
katarinadahlin
PRO
1
570
The #1 spot is gone: here's how to win anyway
tamaranovitovic
4
1.2k
Done Done
chrislema
187
17k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
128
56k
The Limits of Empathy - UXLibs8
cassininazir
2
720
Imperfection Machines: The Place of Print at Facebook
scottboms
270
14k
Design in an AI World
tapps
1
350
Lightning Talk: Beautiful Slides for Beginners
inesmontani
PRO
2
730
Unsuck your backbone
ammeep
672
58k
GraphQLの誤解/rethinking-graphql
sonatard
75
12k
Tell your own story through comics
letsgokoyo
1
1.1k
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.9k
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