Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Random record in ActiveRecord

I'm in need of getting a random record from a table via ActiveRecord. I've followed the example from Jamis Buck from 2006.

However, I've also come across another way via a Google search (can't attribute with a link due to new user restrictions):

 rand_id = rand(Model.count)  rand_record = Model.first(:conditions => ["id >= ?", rand_id]) 

I'm curious how others on here have done it or if anyone knows what way would be more efficient.

like image 703
jyunderwood Avatar asked May 02 '10 02:05

jyunderwood


People also ask

Is ActiveRecord an ORM?

ActiveRecord is an ORM. It's a layer of Ruby code that runs between your database and your logic code.

What does ActiveRecord base do?

ActiveRecord::Base indicates that the ActiveRecord class or module has a static inner class called Base that you're extending.

What is ActiveRecord naming convention?

Active Record uses naming conventions for the columns in database tables, depending on the purpose of these columns. Foreign keys - These fields should be named following the pattern singularized_table_name_id (e.g., item_id , order_id ).


2 Answers

Rails 6

As stated by Jason in the comments, in Rails 6, non-attribute arguments are not allowed. You must wrap the value in an Arel.sql() statement.

Model.order(Arel.sql('RANDOM()')).first 

Rails 5, 4

In Rails 4 and 5, using Postgresql or SQLite, using RANDOM():

Model.order('RANDOM()').first 

Presumably the same would work for MySQL with RAND()

Model.order('RAND()').first 

This is about 2.5 times faster than the approach in the accepted answer.

Caveat: This is slow for large datasets with millions of records, so you might want to add a limit clause.

like image 80
Mohamad Avatar answered Nov 16 '22 00:11

Mohamad


I haven't found an ideal way to do this without at least two queries.

The following uses a randomly generated number (up to the current record count) as an offset.

offset = rand(Model.count)  # Rails 4 rand_record = Model.offset(offset).first  # Rails 3 rand_record = Model.first(:offset => offset) 

To be honest, I've just been using ORDER BY RAND() or RANDOM() (depending on the database). It's not a performance issue if you don't have a performance issue.

like image 23
Toby Hede Avatar answered Nov 15 '22 23:11

Toby Hede