Search code examples
ruby-on-railsactiverecordfindbuilding

Rails 2.3.8: Fetching objects via ActiveRecord without building all the objects


I'm wondering if there's a way to fetch objects from the DB via ActiveRecord, without having Rails build the whole objects (just a few fields).

For example, I sometimes need to check whether a certain object contains a certain field. Let's say I have a Student object referencing a Bag object (each student has one bag). I need to check if a female student exists that her bag has more than 4 pencils.

In ActiveRecord, I would have to do something like this:

exists = Student.female.find(:all, conditions => 'bags.pencil_count > 4', :include => :bag).size > 0

The problem is that if there are a 1000 students complying with this condition, a 1000 objects would be built by AR including their 1000 bags.

This reduces me to using plain SQL for this query (for performance reasons), which breaks the AR. I won't be using the named scopes, and I would have to remember to update them all around the code, if something in the named scope changes.

This is an example, but there are many more cases that for performance reasons, I would have to use SQL instead of letting AR build many objects, and this breaks encapsulation.

Is there any way to tell AR not to build the objects, or just build a certain field (also in associations)?


Solution

  • If you're only testing for the existence of a matching record, just use Model.count from ActiveRecord::Calculations, e.g.:

    exists = Student.female.count(  :conditions => 'bags.pencil_count > 4',
                                    :joins => :bag
                                 ) > 0
    

    count simply (as the name of the class implies), does the calculation and doesn't build any objects.

    (And for future reference it's good to know the difference between :include and :joins. The former eager-loads the associated model, whereas the latter does not, but still lets you use those fields in your :conditions.)