Thursday, October 18, 2007

Finders

Since this is the first post on the find_all_by_accident blog, thought I should start with a post on finders. As I'm not an expert by any stretch, my posts(for a while anyway) will probably pose more questions than answers but I'll bring you through my process of trying to find the answers first and then hopefully some of you have something to add.

So I'm reading Agile Web Development and I'm looking at finders and I'm wondering what is the difference between :select and :include. I want to just come out and ask but I know that's just plain lazy so I'll check the API first..

Ok so here are the respective definitions

:include

Names associations that should be loaded alongside using LEFT OUTER JOINs. The symbols named refer to already defined associations. See eager loading under Associations.


:select

By default, this is * as in SELECT * FROM, but can be changed if you for example want to do a join, but not include the joined columns.

hmm...well still a little confused but it tells me to "see eager loading" so lets do that....

Ahhh, interesting, seems ":select" is just like the sql select which is only going to return certain columns from the db which is important for performance because there's no need to pull all the columns if you don't need them.

But :Include encompasses all ASSOCIATIONS, so its really critical if for example you are trying to return all the comments and the author for each post in a collection of posts.

doing a loop like

for post in Post.find(:all)
puts "Post: " + post.title
puts "Written by: " + post.author.name
puts "Last comment on: " + post.comments.first.created_on
end

That results in 201 db queries for 100 posts, but by using

for post in Post.find(:all, :include => [ :author, :comments ])

It brings it all down to a single query. Big difference.