5

シャッフルされたActiveRecordクエリをページ分割しようとしています。カミナリジェムを使用してこれを行うための構文は次のとおりです。

@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()関数を使用してランダム化を実行することをお勧めします。シード値を渡して、シャッフルがセッションごとに 1 回だけ行われるようにすることもできます。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 に答える