Ordering with included models
Is there a way to order results using a column from a model and a column from a related model via includes? Here is a scenario:
A product that has many parts, each of which has a numerical value and is linked to an item. What I would like to do when listing the parts is have them sorted/ordered first by their numerical value and then by the related item name. For example, if there are parts with numerical values (the letter indicates the related item name)
A : 10
B : 10
C : 50
they should be listed on the page as follows (numerical value DESC and the related item name ASC):
C 50
A 10
B 10
I am able to sort them by either numerical value or the related item name from the product model name but cannot do by both values as decried above using either models or controllers (the controller sorting defaults to created_at ASC).
All the solutions I found show how to order using multiple columns from a single model even when including a related model but not when ordering is done using columns from two related models. Because I am fetching multiple products per page, I get parts for each product using
product.parts.includes(:items)
Anyway, it is possible that I am overlooking something simple and that this has a straightforward solution so any pointers will be much appreciated.
Thanks in advance.
OK, I got it figured and posting here in case someone finds it useful.
I modified the Product model as follows
# product.rb
has_many :parts, -> { includes(:item).order(:part_numerical_value => :desc).order("items.name asc") }
The reason for doing this in the Product model is because I am listing multiple products on a page and using product.parts
to get all matching parts for each product listed on the page (in the view).
The reason why the Item is singular in the includes part is because each part has a single item. Using includes(:items)
results in an error when rendering the view. I use items in the ordering statement (i.e., "order("items.name asc")
because it refers to the table name (SQL code).
I have tested this with multiple includes and it works fine. There is no particular order in which, ahem, ordering statements needs to be listed (i.e, in the above example, you don’t need to order first by a part column) so use whatever your app requires.