0

Table - Contacts

Name     Channel
Teejay   Friends
John     Colleagues
Rick     Friends
Carl     Business
Vulcan   Business
Scott    Office
Alex     Friends

How do I out put records from this table, 'randomly'. Well, not exactly random. I should be able to output the records wherein no records with the same Channel be beside each other.

A record in the `Friends` Channel
A record in the `Colleagues` Channel
A record in the `Business` Channel
A record in the `Office` Channel
A record in the `Friends` Channel
A record in the `Business` Channel
A record in the `Friends` Channel

More Info:

Friend model, Colleague model, Business model, Office model are child models of Contact.

Teej
  • 12,764
  • 9
  • 72
  • 93

1 Answers1

1

What do you think about this?

[ Friend, Colleague, Business, Office ].each do |klass|
  klass.find(:first, :offset => (klass.count * rand).to_i, :limit => 1)
end

This fetches one entry from every child models. This won't be so fast, but works :)

If you need two iterations, you can wrap the whole block into a:

2.times do
end

But be aware of that order of the models is fixed here. If you need that random as well:

prev = nil
10.times do
  klass = [ Friend, Colleague, Business, Office ].reject { |k| k == prev }.shuffle.first
  p klass.find(:first, :offset => (klass.count * rand).to_i, :limit => 1)
  prev = klass
end

Update:

For curiosity I made a small method for that. Keep in mind that you need to replace the RAND() to RANDOM() if you're using SQLite. And please check this question as well.

def get_random_items(classes, count)
  # collect at least count / 2 random items from each class
  items = Hash.new do |hash,klass|
    hash[klass] = klass.find(:all, :order => "RAND()", :limit => (count.to_f / 2).ceil)
  end

  results = []
  prev = nil

  while (classes.length > 0 && results.length < count) do
    klass = classes.shuffle!.pop

    item = items[klass].pop
    next unless item

    classes << prev if prev
    prev = (items[klass].length > 0) ? klass : nil
    results << item
  end

  results

end

Usage: get_random_items([ Friend, Colleague, Business, Office ], 10)

Community
  • 1
  • 1
KARASZI István
  • 30,900
  • 8
  • 101
  • 128