views:

112

answers:

4

I'm a beginner at rails. And I've come to understand two different ways to return the same result.

What is the difference between these two? And what situation would require you to choose one from the other?

Example 1:

Object.find(:all).select {|c| c.name == "Foobar" }.size

Example 2:

Object.count(:conditions => ['name = ?', 'Foobar'])

FURTHER NOTE:

I seriously wish I could vote everyone correct answers for this one. Thank you so much. I just had a serious rails affirmation.

+4  A: 

Object.count always hits the DB, and the find()....size() call can optimize. Good discussion here

http://rhnh.net/2007/09/26/counting-activerecord-associations-count-size-or-length

Lou Franco
Granted, so why does the first one exist? ;D
Trip
Simple - what if you need the data, AND you need a count?
jasonpgignac
I was wrong -- the second one always uses select count ... to the DB. Find and size can sometimes be smarter.
Lou Franco
The first one combines 3 different methods, you would use it, if you still wanted to fetch all objects regardless of the count.
Teoulas
Would this be relative to the above example? 1.) - if Object.name == "Foobar" / 2.) if Object(:conditions => ['name = ?' ,'Foobar']) ?
Trip
+2  A: 

In example 1, you are getting all objects from the datastore, and then iterating over all of them, selecting the objects that has the name Foobar. And then getting the size of that array. Example 1 is the clear loser here.

Example 1 sql:

select * from whatever
# then iterate over entire array

Example two executes a where clause in SQL to the datastore.

select count(id) from whatever where name = 'foobar'
# The SQL above is sql-server accurate, but not necessarily mysql or sqlite3
Jesse Wolgamott
@jesse, amazing. But why would anyone then ever use the first example?
Trip
@trip To answer your question below, "Why does 1 exist" --- #1 is really three methods, a Find and then an Array (select) method, and another Array (count) method.
Jesse Wolgamott
@trip -- no one should ever use #1 as it is written.... but if you do have an object array, you'll want to use select/collect to manipulate your array into other arrays. map/reduce type of stuff.
Jesse Wolgamott
+4  A: 

Example 1:

This constructs a query:

SELECT * FROM objects

then turns all the records into a collection of objects in your memory, then iterates through every object to see if it meets the condition, and then counts the number of elements that meet condition.

Example 2:

This constructs a query:

SELECT count(id) FROM objects WHERE name = 'Foobar'

lets sql do all the hard work, and returns just an integer - a number of objects meeting condition.

Usually you want no 2 - faster and less memory

Krzysztof
+2  A: 

Example 1 will load all of your records from the DB (assuming Object is an ActiveRecord model), then uses Ruby to reduce the set, and then return the size of that array. So this is potentially memory and CPU heavy - not good.

Example 2 performs the count in SQL, so all the heavy lifting is performed in the database, not in Ruby. Much better :)

keeran
Would this be relative to the above example? 1.) - if Object.name == "Foobar" / 2.) if Object(:conditions => ['name = ?' ,'Foobar']) ?
Trip