Solution 1:

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.

Solution 2:

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.