From 5054c7e31976b10d3cd65bebb37d446f5fcaabb8 Mon Sep 17 00:00:00 2001 From: Rob Date: Sun, 8 Oct 2017 00:45:28 +0000 Subject: [PATCH] Order attributes by association if it exists Adding an order clause to the relation for an associated attribute was having no effect on the dashboard's sorting. When the order is applied, the current relation will check if the attribute is an association and reorder by count on the attribute's id column or on the relation's {attribute}_id column following the Rails convention of naming FK columns. The relation order method was changed to reorder to override any default scoping that may exist for the relation. https://github.com/thoughtbot/administrate/issues/471 --- lib/administrate/order.rb | 43 ++++++++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/lib/administrate/order.rb b/lib/administrate/order.rb index 3c083b41b0..88d09b1b2a 100644 --- a/lib/administrate/order.rb +++ b/lib/administrate/order.rb @@ -6,11 +6,13 @@ def initialize(attribute = nil, direction = nil) end def apply(relation) - if relation.columns_hash.keys.include?(attribute.to_s) - relation.order("#{attribute} #{direction}") - else - relation - end + return order_by_association(relation) if + !reflect_association(relation).nil? + + return relation.reorder("#{attribute} #{direction}") if + relation.columns_hash.keys.include?(attribute.to_s) + + relation end def ordered_by?(attr) @@ -41,5 +43,36 @@ def reversed_direction_param_for(attr) def opposite_direction direction.to_sym == :asc ? :desc : :asc end + + def order_by_association(relation) + return order_by_count(relation) if has_many_attribute?(relation) + + return order_by_id(relation) if belongs_to_attribute?(relation) + + relation + end + + def order_by_count(relation) + relation. + left_joins(attribute.to_sym). + group(:id). + reorder("COUNT(#{attribute}.id) #{direction}") + end + + def order_by_id(relation) + relation.reorder("#{attribute}_id #{direction}") + end + + def has_many_attribute?(relation) + reflect_association(relation).macro == :has_many + end + + def belongs_to_attribute?(relation) + reflect_association(relation).macro == :belongs_to + end + + def reflect_association(relation) + relation.klass.reflect_on_association(attribute.to_s) + end end end