开发者

Rails: Getting random product within several categories

I have a question about random entries in Rails 3. I have two models:

class Product < ActiveRecord::Base
  belongs_to :category

  self.random
    Product.find :first, :offset => ( Product.count * ActiveSupport::SecureRandom.random_number ).to_i
  end
end

class Category < ActiveRecord::Base
  has_many :products
end

I'm able to get a random product within all products using an random offset castet to int. But I want also be able to get random products WITHIN several given categories. I tried something like this, but this doesn't work, because of the offset index:

class Product < ActiveRecord::Base
  belongs_to :category
  self.random cat=["Mac", "Windows"]
    joins(:categories).where(:categories => { :name => cat }).where(:first, :offset => ( Product.count * ActiveSupport::SecureRandom.random_number ).to_i)
  end
开发者_C百科end

Anybody here who knows a better solution?

thx! tux


You could try and simplify this a little:

class Product < ActiveRecord::Base
  def self.random(cat = nil)
    cat ||= %w[ Mac Windows ]

    joins(:categories).where(:categories => { :name => cat }).offset(ActiveSupport::SecureRandom.random_number(self.count)).first
  end
end

Rails 3 has a lot of convenient helper methods like offset and first that can reduce the number of arguments you need to pass to the where clause.

If you're having issues with the join, where the number of products that match is smaller than the number of products in total, you need to use ORDER BY RAND() instead. It's actually not that huge a deal performance wise in most cases and you can always benchmark to make sure it works for you.


the offset happens after the order, so you can add .order('rand()') then you will be getting random elements from multiple categories. but since the order is random you also do not need offset anymore. so just:

class Product < ActiveRecord::Base
  belongs_to :category
  self.random cat=["Mac", "Windows"]
    joins(:categories).where(:categories => { :name => cat }).order('rand()').first
  end
end
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜