Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ActiveRecord.find(array_of_ids), preserving order

When you do Something.find(array_of_ids) in Rails, the order of the resulting array does not depend on the order of array_of_ids.

Is there any way to do the find and preserve the order?

ATM I manually sort the records based on order of IDs, but that is kind of lame.

UPD: if it's possible to specify the order using the :order param and some kind of SQL clause, then how?

like image 946
Leonid Shevtsov Avatar asked Nov 05 '09 13:11

Leonid Shevtsov


2 Answers

Oddly, no one has suggested something like this:

index = Something.find(array_of_ids).group_by(&:id) array_of_ids.map { |i| index[i].first } 

As efficient as it gets besides letting SQL backend do it.

Edit: To improve on my own answer, you can also do it like this:

Something.find(array_of_ids).index_by(&:id).slice(*array_of_ids).values 

#index_by and #slice are pretty handy additions in ActiveSupport for arrays and hashes respectively.

like image 95
Gunchars Avatar answered Nov 15 '22 23:11

Gunchars


The answer is for mysql only

There is a function in mysql called FIELD()

Here is how you could use it in .find():

>> ids = [100, 1, 6] => [100, 1, 6]  >> WordDocument.find(ids).collect(&:id) => [1, 6, 100]  >> WordDocument.find(ids, :order => "field(id, #{ids.join(',')})") => [100, 1, 6]  For new Version >> WordDocument.where(id: ids).order("field(id, #{ids.join ','})") 

Update: This will be removed in Rails 6.1 Rails source code

like image 33
kovyrin Avatar answered Nov 16 '22 00:11

kovyrin