Search code examples
ruby-on-railsrubyrails-activerecord

Possible to sort by letter grades?


I have a table that I'd like to sort by letter grade. The issue is that it sorts letters before letters with symbols. For example, it sorts: A, A+, A-, B, B+, B-, etc., but I would like it to sort A+, A, A-, B+, B, B-, etc. Is there a way to set do this?


Solution

  • As idea you can check last letter of grade and depending on its value add some number to grade

    You can add scope to your model

    scope :order_by_grade, -> do
      sql = <<~SQL
        CASE RIGHT(grade, 1)
        WHEN '-' THEN grade || 3
        WHEN '+' THEN grade || 1
        ELSE grade || 2
        END
      SQL
    
      order(sql)
    end
    

    And then apply to your model Work.order_by_grade

    As another idea you can define some constant in the model with all variants and use index

    And may be better sort from the worst to the best as ASC and from the best to the worst as DESC -- it's your choice

    GRADES = %w[A+ A A- B+ ...]
    
    scope :order_by_grade, -> do
      sql = 'CASE grade '
    
      GRADES.reverse_each.with_index do |grade, index|
        sql << sanitize_sql_array(['WHEN ? THEN ?', grade, index])
      end
    
      sql << ' END'
    
      order(sql)
    end
    

    And then apply to your model Work.order_by_grade or even Work.order_by_grade.reverse_order