Random Records in Rails

by Trevor Turk

There are a number of different ways to retrieve random items from a database in Rails, most of which have been discussed at length on the Rails wiki. According to this article, there are 3 preferred methods:

  1. Select a Record by Random Offset
  2. Randomize with the Database
  3. Randomize with Ruby

For an in-depth look into these options, you can peruse this discussion page, which details some of the pros and cons of different strategies for randomization.

After trying out a few of the techniques that abound in this area, I stumbled across an article from Jamis Buck, where he discusses a RESTful way to approach the creation of custom finders. Although randomization isn’t the focus of the article, he does provide a bit of guidance in that regard. His strategy uses Ruby for the randomization, and employs 2 light-weight queries. The first query gathers a list of valid ids. The second simply selects a single item using that (randomized) id.

So, I did a bit of cargo-culting and repurposing to achieve an efficient, database agnostic way to retrieve random items from a database using ActiveRecord. Simply add the following to the model from which you’d like to be able to pull random records:

class Widget < ActiveRecord::Base

  # ...

  def self.random
    ids = connection.select_all("SELECT id FROM widgets")
    find(ids[rand(ids.length)]["id"].to_i) unless ids.blank?
  end

end

Then, you can use the following bit of code in a controller like so:

class SomeController < ApplicationController

  # ...

  def some_action
    @widget = Widget.random
  end

end

And you’ve got a small and efficient “random finder” for use throughout your app. Lovely.

Update I just came across a comment from Rails Core member Koz that provides an alternative that seems compelling at fist glance:

http://gist.github.com/358505.js?file=gistfile1.ru

Advertisement