我正在尝试对洗牌的ActiveRecord查询进行分页。使用Kaminari gem执行此操作的语法是:
@users = Kaminari.paginate_array(User.all.shuffle).page(params[:page]).per(20)
这个问题是User.all
在每个分页请求上重新洗牌,导致重复记录被调用。有没有办法防止这种重复?
答案 0 :(得分: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链接
答案 1 :(得分:3)
正如KandadaBoggu指出的那样,当您只需要20时,从数据库中检索所有User
记录效率很低。我建议使用MySQL's RAND()
function来执行之前的随机化 >您从数据库返回。您仍然可以将种子值传递给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安装,但这应该比原始代码执行得更好。
答案 2 :(得分: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
很可能会产生相同的结果。