2

If I have records with ids: 1,2,3,4 and want sort them a certain way, like this 1, 4, 2, 3, how can I do this?

I think something like that, but it doesn't work of course.

Service.all.order(id: [1, 4, 2, 3])
Croaton
  • 1,812
  • 3
  • 18
  • 28

2 Answers2

2

Justin Weiss wrote a blog article about this problem just two days ago.

It seems to be a good approach to tell the database about the preferred order and load all records sorted in that order directly from the database. Example from his blog article.

Add the following extension to your application:

# e.g. in config/initializers/find_by_ordered_ids.rb
module FindByOrderedIdsActiveRecordExtension
  extend ActiveSupport::Concern
  module ClassMethods
    def find_ordered(ids)
      order_clause = "CASE id "
      ids.each_with_index do |id, index|
        order_clause << "WHEN #{id} THEN #{index} "
      end
      order_clause << "ELSE #{ids.length} END"
      where(id: ids).order(order_clause)
    end
  end
end

ActiveRecord::Base.include(FindByOrderedIdsActiveRecordExtension)

That would allow you to write queries like this:

Service.find_ordered([2, 1, 3]) # => [2, 1, 3]
spickermann
  • 100,941
  • 9
  • 101
  • 131
  • Hm, now ```find_by_ordered_ids.rb:1:in `': uninitialized constant Extensions (NameError)``` – Croaton Apr 22 '15 at 02:02
  • @VitalyFry : I removed the namespaces from the original example. Please try again. – spickermann Apr 22 '15 at 02:10
  • I recommend you replace `order_clause = "CASE id "` with `order_clause = "CASE #{self.table_name}.id "`. This will prevent any ambiguous queries when using Joins and whatnot. – Joshua Pinter Dec 09 '17 at 21:11
0
 order = [1,4,2,3]
 @services = []
   order.each do |id|
   @services << Services.find(id)
   end
Beartech
  • 6,173
  • 1
  • 18
  • 41
  • This is very inefficient, because it would make N (size of the array) queries to the database instead of just one. – spickermann Apr 22 '15 at 01:00
  • Totally agree. The OP did not mention if they cared how many queries would take place or if they were ever going to do more than the 4 used in their example. – Beartech Apr 22 '15 at 13:39