Easily select random records in rails
If you ever wondered how to easily retrieve a random record in an ActiveRecord model, here’s en easy way to do that: use the sample method.
sample is a class method from the Array class that retrieves one or more random items from an array instance. It conveniently returns nil or an array lesser than the items requested if the original array has not enough items.
Since all ActiveRecord finds return an array, you can easily add the sample call at the end of a find call to get the random items you need from complex queries.
For example, imagine you have a Book model which has a published_at datetime attribute and you want to show, in your library home page, a random selection of 5 books that have been published. You can easily get those using this snippet:
def get_random_books_for_home_page find(:all).sample(5) end
EDIT (30/11/2012): after revisiting this post I obviously found out that this is in fact a very inefficient way to get random records for large collections, as Rails will have to instantiate them all, then performing a random on them. Unfortunately, seems like the only way to get a true random collection of items is to perform the sort on the database engine and then getting the first n elements of the resulting query, which will also be slow for large collections. This can be done like this:
def get_random_books_for_home_page Books.order("RAND()").first(5) end
In this case we tell mySQL to sort the collection using the internal
RAND() method. One problem with this solution is that it’s database-engine specific (the sorting method may be named different in other engines, and in fact at least in PostgreSQL is). Other solutions try to get pseudo random records using the id column, for example by getting the n first records which id is greater or lower than a certain number. While this may be ok in most cases (considering you use a random index to compare with based on the min and max for id values) it may not be so good in other cases.