Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 33 additions & 16 deletions lib/administrate/order.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,10 @@ def apply(relation)
return order_by_association(relation) unless
reflect_association(relation).nil?

order = relation.arel_table[sorting_column].public_send(direction)
return order_by_column(relation) if
column_exist?(relation, sorting_column)

tiebreak_key = relation.primary_key
tiebreak_order = relation.arel_table[tiebreak_key].public_send(direction)

if column_exist?(relation, sorting_column)
if column_exist?(relation, tiebreak_key) && sorting_column.to_s != tiebreak_key.to_s
relation.reorder(order, tiebreak_order)
else
relation.reorder(order)
end
else
relation
end
relation
end

def ordered_by?(attr)
Expand Down Expand Up @@ -59,14 +49,22 @@ def opposite_direction
(direction == :asc) ? :desc : :asc
end

def order_by_column(relation)
order = relation.arel_table[sorting_column].public_send(direction)
with_tiebreak(
relation.reorder(order),
ordered_column: sorting_column
)
end

def order_by_association(relation)
case relation_type(relation)
when :has_many
order_by_count(relation)
with_tiebreak(order_by_count(relation))
when :belongs_to
order_by_belongs_to(relation)
with_tiebreak(order_by_belongs_to(relation))
when :has_one
order_by_has_one(relation)
with_tiebreak(order_by_has_one(relation))
else
relation
end
Expand Down Expand Up @@ -112,6 +110,25 @@ def column_exist?(table, column_name)
table.columns_hash.key?(column_name.to_s)
end

def with_tiebreak(relation, ordered_column: nil)
tiebreak_key = relation.primary_key
tiebreak_order = tiebreak_order_for(relation)

if tiebreak_order && ordered_column.to_s != tiebreak_key.to_s
relation.order(tiebreak_order)
else
relation
end
end

def tiebreak_order_for(relation)
tiebreak_key = relation.primary_key

if tiebreak_key && column_exist?(relation, tiebreak_key)
relation.arel_table[tiebreak_key].public_send(direction)
end
end
Comment on lines +113 to +130

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having to do tiebreak_key = relation.primary_key twice smells a bit wrong to me. I wonder if we can do this differently, perhaps making these functions a bit more generic and less tied to the concept of tiebreak. Perhaps even usable elsewhere in the class... For now, would this make sense?

Suggested change
def with_tiebreak(relation, ordered_column: nil)
tiebreak_key = relation.primary_key
tiebreak_order = tiebreak_order_for(relation)
if tiebreak_order && ordered_column.to_s != tiebreak_key.to_s
relation.order(tiebreak_order)
else
relation
end
end
def tiebreak_order_for(relation)
tiebreak_key = relation.primary_key
if tiebreak_key && column_exist?(relation, tiebreak_key)
relation.arel_table[tiebreak_key].public_send(direction)
end
end
def with_tiebreak(relation, ordered_column: nil)
tiebreak_key = relation.primary_key
if ordered_column.to_s != tiebreak_key.to_s
sort_by(relation, tiebreak_key)
else
relation
end
end
def sort_by(relation, column)
if column && column_exist?(relation, column)
order = relation.arel_table[column].public_send(direction)
relation.order(order)
else
relation
end
end

This breaks some examples in spec/lib/administrate/order_spec.rb, but they are testing the private method which is also a bad smell anyway.


def order_by_id_query(relation)
relation.arel_table[association_foreign_key(relation)].public_send(direction)
end
Expand Down
Loading