SausageBuscuit
SausageBuscuit

Reputation: 1296

Ruby on Rails sort on the result of a method

I have a helper method in a Rails site that checks how many attendees are in a certain class. I have two different entities here, one for the class and one for attendee. The helper method takes an activerecord result as an argument and calculates how many open slots there are based on the total spots minus the total people that have registered. Is there any way that I can sort by the result of this so that courses with no open spots are put at the end of the list? Don't know if it will affect anything, but I am also using the will_paginate gem on the result set as well. I am currently ordering by the start date.

Method in math_class.helper

def open_slots(math_class)
  math_attendees = Attendee.where(:math_class_id => math_class.id).count
  return math_class.total_spots - math_attendees
end

Math Class View/Open Slots Column

<% @math_classes.each do |math_class| %>
   <!-- Other columns... -->
<% if open_slots(math_class) > 0 %>
  <td>
   <%= pluralize(open_slots(math_class), 'slot') %> of 
   <%= math_class.total_spots %> remaining
   </td>
<% else %>
   <td><span class="text-error">No Open Slots</span></td>
<% end %>

Controller Query statement

@math_classes = MathClass.joins(:room).order("starts_at").page(params[:page]).per_page(100)

Upvotes: 0

Views: 389

Answers (2)

Nick Aschenbach
Nick Aschenbach

Reputation: 191

Consider using the block form of Array#sort:

 @math_classes = MathClass.joins(:room).order("starts_at").page(params[:page]).per_page(100)
 @math_classes.to_a.sort! do |a, b|
   a_open_spots = a.total_spots - a.attendees.count
   b_open_spots = b.total_spots - b.attendees.count
   a_open_spots <=> b_open_spots
 end

The spaceship operator <=> returns -1, 0 or 1 depending on if the left hand side is less than, equal to or greater than the right side. For example:

 3 <=> 4 # => -1
 3 <=> 3 # => 0
 4 <=> 3 # => 1

Array#sort uses this to order the elements in the array.

Upvotes: 1

baron816
baron816

Reputation: 701

You're going to have to use the order_by Ruby method.

Upvotes: 0

Related Questions