Brian Corrales
corralesonline.com

Ordering Eager-loaded Data

February 1st, 2008 . by brian.corrales

If you are using Active Record with Ruby on Rails, I’m sure you’re familiar with the :include symbol for the find method. Here’s an example where we have a category structure of Categories -> SubCategories:

@category = Category.find(params[:id], :include => [:sub_categories])

This will find the category with id = params[:id] and will eager load all of the related sub categories. This way we only need to run one query, rather than two. We could also do this

@category = Category.find(params[:id], :include => [:sub_categories, {:sub_categories => :products }])

Now we are going down another level and retrieving all products related to each sub_category. Unfortunately, there is no way to go travel further into your data model with the :includes symbol. If anyone has a good approach, I’m all ears.

The problem I’ve run into is that my Category model has has_many :sub_categories, :order => ‘rank asc’. When I include :sub_categories, Active Record does not recognize my ordering. This caused me quite a few headaches until I came across this in the docs:

” Since the eager loading pulls from multiple tables, you‘ll have to disambiguate any column references in both conditions and orders. So :order => “posts.id DESC” will work while :order => “id DESC” will not. Because eager loading generates the SELECT statement too, the :select option is ignored.” Here’s the link:

So the best approach would be @category = Category.find(params[:id], :include => [:sub_categories, {:sub_categories => :products}], :order => “categories.rank, sub_categories.rank”)

This will order your categories and sub categories. Hopefully someone finds this useful. If you have come up with a better approach, please let me know.

[?]
Share This

Leave a Reply

Name

Mail (never published)

Website