Active Record No No's

20
Active Record No Nos Use your common sense

description

Avoid the most common pitfalls of Active Record and reduce load on your database

Transcript of Active Record No No's

Page 1: Active Record No No's

Active Record No NosUse your common sense

Page 2: Active Record No No's

About me

Patrick Hüsler

Freelance developer

Apple enthusiast

Surfing and Kung Fu

Page 3: Active Record No No's

AR Kool AidNo giant xml mapping file

Dynamic finders

Associations

Inheritance

Polymorphism

...

Page 4: Active Record No No's

IT’S ALMOST WIZARDRY!!!!

Page 5: Active Record No No's

BUT...

Page 6: Active Record No No's
Page 7: Active Record No No's

SO...

Page 8: Active Record No No's

Be reasonable or ...

Page 9: Active Record No No's
Page 10: Active Record No No's

Code like this

@user.friends.map {|friend| friend.id}

Page 11: Active Record No No's

Or this

@user.friends.sort_by{ |friend| [ friend.online? ? 1 : 0,friend] }

Page 12: Active Record No No's

Or this

friends.accepted.map{ |friend| friend.logs.visible_for(self) }.flatten

Page 13: Active Record No No's

eventually leads to

Page 14: Active Record No No's

THIS

Page 15: Active Record No No's

We can do better ...

Look at the generated SQL

Create indices

Let AR/SQL do the math (conditions,count,sum, named_scope, ...)

Paginate, but paginate in SQL not on ruby collections

Only fetch what you really need (:select => :id)

Use :include (n + 1 problem)

Page 16: Active Record No No's

Check SQL logs

tail -f log/*.log

Log to STDOUT in script/console

Do it once in ~/.irbrc

Use one of the query analyzer plugins

Use profiling tools like New Relic RPM, FiveRuns TuneUp or Rack::Bug (Check railscast)

Page 17: Active Record No No's

Where to look

Iterations/calculations in views / partials

Calculations on potentially big collections in ruby that can be done in SQL

@user.friends.recent.sort_by{ |friend| [ friend.online? ? 1 : 0,friend] }

Pagination on collection instead of SQL

User.all.paginate(:per_page => 1, :page => 1)

Page 18: Active Record No No's

Where to lookNot eager loaded associations

Post.all.each{|post| puts post.author.name}

Classic n + 1 problem

Post.all(:include => :author)

Ruby is used for tasks that could be done with SQL

Post.all.map(&:id)

Instead of Post.all(:select => :id)

Page 19: Active Record No No's

Image ressourceshttp://www.gunaxin.com/wp-content/uploads/2009/05/kool_aid_man_glass.jpg

http://www.thinkingfinance.net/blog/wp-content/uploads/2009/04/koolaidman.gif

http://tux.crystalxp.net/png/chozo-mj-tux-gandalf-le-gris-1887.png

http://icanhascheezburger.files.wordpress.com/2009/01/funny-pictures-cat-does-not-li

http://midlifeslices.files.wordpress.com/2009/02/explosion-finger.jpg

http://bmorearty.files.wordpress.com/2008/06/test-log-with-titles.png

http://www.adoptedthemovie.com/wp-content/uploads/Picture_005.png

http://comps.fotosearch.com/comp/TBZ/TBZ175/dynamite-magnifying-glass_~DYN014.jpg