5

我正在尝试对打乱的 ActiveRecord 查询进行分页。使用 Kaminari gem 执行此操作的语法是:

@users = Kaminari.paginate_array(User.all.shuffle).page(params[:page]).per(20)

这个问题是User.all在每个分页请求上重新洗牌,导致重复记录被调用。有没有办法防止这种重复?

4

3 回答 3

5

您需要在查询之间为 rand 传递种子

params[:seed] ||= Random.new_seed
srand params[:seed].to_i
@users = Kaminari.paginate_array(User.all.shuffle).page(params[:page]).per(20)

并在视图中将 params[:seed] 添加到所有页面的 kaminari 链接

于 2012-04-01T19:31:13.927 回答
3

正如上面 KandadaBoggu 所指出的,User当您只需要 20 条记录时,从数据库中检索所有记录是低效的。我建议您在从数据库返回之前使用MySQL 的RAND()函数来执行随机化。您仍然可以将种子值传递给以确保每个会话只发生一次洗牌。RAND()

例如:

class User < ActiveRecord::Base
  def self.randomized(seed = nil)
    seed = seed.to_i rescue 0
    order("RAND(#{seed})")
  end
end

class UsersController < ApplicationController
  before_filter :set_random_seed

  def index
    @users = User.randomized(session[:seed]).page(params[:page]).per(20)
  end

private

  def set_random_seed
    session[:seed] ||= Random.new_seed
  end
end

我没有要测试的 MySQL 安装,但这应该比您的原始代码执行得更好。

于 2012-04-12T21:15:27.253 回答
0

你也可以这样做:

class UsersController < ApplicationController
  USERS_SEED = 1000 # Or any another not-so-big number

  def set_random_seed
    session[:seed] ||= Random.rand(USERS_SEED)
  end
end   

因为Random.new_seed如果您的数据不是那么大,很可能会产生相同的结果。

于 2015-04-28T13:42:08.707 回答