Ordering Eager-loaded Data
Posted in: Ruby on Rails
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.
Return to: Ordering Eager-loaded Data
Social Web