I'd go with something like this:
object.sort_by do |o|
[
(o[:type] == :sort) ? 0 : 1,
sortIdOrder.index(o[:id])
]
end
When sorting by an array, you're essentially sorting by the first element, except when they're the same, in which case you sort by the second element, etc. In code above, (o[:type] == :sort) ? 0 : 1 ensures that everything with a type of :sort comes first, and everything else after, even if the type is nil, or 5 or whatever you like. The sortIdOrder.index(o[:id]) term ensures things are sorted as you like (though items with no :id, or whose :id is not found in sortIdOrder will be ordered arbitrarily. If your data set is very large, you may want to tweak this further so that the sortIdOrder array is not performed for non-sort items.
Enumerable#sort_by only has to call the block once for each element, and then perform fast comparisons on the results; Enumerable#sort has to call the block on pairs of elements, which means it's called more often:
irb(main):015:0> ary = %w{9 8 7 6 5 4 3 2 1}
=> ["9", "8", "7", "6", "5", "4", "3", "2", "1"]
irb(main):016:0> a = 0; ary.sort_by {|x| puts x; a+=1; x.to_i }; puts "Total: #{a}"
9
8
7
6
5
4
3
2
1
Total: 9
=> nil
irb(main):017:0> a = 0; ary.sort {|x,y| puts "#{x},#{y}"; a+=1; x.to_i <=> y.to_i }; puts "Total: #{a}"
9,5
5,1
8,5
2,5
7,5
3,5
6,5
4,5
6,8
8,9
7,8
6,7
1,3
3,4
2,3
1,2
Total: 16
=> nil
In these cases, it's really not very important, because hash access is fast anyway (though sort_by is still more legible), but in cases where calculating the attribute you want to sort by is even moderately expensive, sort_by can be quite a bit faster. The block form of sort is mostly useful if the comparison logic itself is complicated.
sort_id_order.