I think you have the logic in the wrong place. You should be using an SQL CASE statement to do the sorting inside the database, that will make it easier to combine this sorting with other query components (such as subqueries and secondary sorting keys). For example, you could have a constant like this:
EXECUTIVES = [ 'President', ... ]
and then a scope like this in your model:
def self.order_by_rank
q = connection.method(:quote)
order([
'case members.executive_position',
*EXECUTIVES.length.each_with_index.map { |s, i| "when #{q[s]} then #{i}" },
"else #{EXECUTIVES.length}",
'end'
].join(' '))
end
With that you could say things like:
Member.order_by_rank
Member.where(...).order_by_rank.order(:name)
A straight forward modification to the order_by_rank scope would give you an in_this_order('President', 'Vice President', 'Treasurer', ...) scope:
def self.in_this_order(*titles)
q = connection.method(:quote)
order([
'case members.executive_position',
*titles.each_with_index.map { |s, i| "when #{q[s]} then #{i}" },
"else #{titles.length}",
'end'
].join(' '))
end
You could also put the titles and their order in a database table:
title | pos
-----------------+----
'President' | 1
'Vice President' | 2
...
and then JOIN to it and ORDER BY pos.