nunojob:~ dscape/08$ echo The Black Sheep

Random in Ruby on Rails

So your doing a find on your model and you want a random instance. I didn’t find a method to do this so I decided to make my own.

In this case I wanted a random quote. So after generating the model all I had to do was:

def self.random
  Quote.find_by_id rand(Quote.count) + 1

And now you can simply call your random quotes in any controller action you desire. Just

@rquote = Quote.random

If this is the lamest ruby ever please feel free to give me some feedback :) I will be delighted to learn a different way!

[EDIT: Discussion about this at Rails Core]

Comments on: "Random in Ruby on Rails" (10)

  1. Quote.find(:first, :order => “RAND()”)

    Apesar de te mandar os índices à fava, sempre deve ser mais rápido que trazeres tudo atrás ;)

  2. Obrigado André.

    Apesar dessa solução não me servir. É que nums database systems é RAND, noutros é RANDOM, noutros mais infelizes é NEWID().

    Têm que ser algo do proprio rails. Senão assim acho que é impossivel ir lá :)

  3. Não trazer a tralha toda:

    Quote.find_by_id rand(Quote.count) + 1

  4. André Medeiros said:

    Talvez seja mais eficiente extenderes as classes dos adaptadores para que contenham uma propriedade que te dá o comando de random, e fazeres algo do género:

    class ModeloQualquer < ActiveRecord::Base
    def self.find(*args)
    if args.first.to_s == "random"
    super(:first, :order => self.random_command)

    Terias que implementar o metodo self.random_command que dependendo do adaptador te retornava uma string. O ideal é extenderes a classe ActiveRecord::Base

  5. Para tabelas com mais de umas centenas de registos, usar RANDOM() ou RAND() não funciona.

    O outro problema de pesquisar por um numero random é caso não exista um registo. Se for um cluster, tudo bem, mas se não existirem registos e existirem saltos nos ids, não irá funcionar correctamente.

    Eis como o fazer correctamente do ponto de vista da eficiência:

  6. Quando digo não funciona, refiro-me a ser muito lento.

  7. Quote.find(:first, :order => ‘RAND()’)
    This way you don’t call .count (a unneeded SQL query).
    And your method is just AWFUL. Imagine you have 100 Quotes, then you delete the first 50. Now your rand(Quote.count) will return from 0 to 50, while your quotes id’s begin with 50. You’ll have no more quotes on your site.
    Please rethink what you wrote, I beg you =)

  8. @labria: no quote will be deleted. its a static data model. so my solution is perfect for my problem, but not for all.

    RAND is mysql only btw.

  9. Thanks

  10. It’s been a long time since this blog has posted… Just want to make a little comment about this method. If your database in the table does not have continuous ID, it can return ‘nil’. The caller needs to validate it. Theoretically, this method is inefficient with table which has very large distribution of ID number (a lot of creation and deletion). But it is a solution to keep in mind…

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: