2012-04-01 12 views
5

シャッフルされたActiveRecordクエリのページを作成しようとしています。雷の宝石を使用してこれを行うための構文は次のとおりです。これでシャッフルされたActiveRecordクエリのページ番号

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

問題はUser.allが重複したレコードが呼び出される原因と、各ページネーション要求に再シャッフルされていることです。このような重複を防ぐ方法はありますか?あなたは、クエリ

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

とビューでの間のランドのための種を渡す必要が

+1

'User.all'を呼び出すと、サーバーの速度が大幅に低下する可能性があります。 100人のユーザーしかいなくても、すべてのユーザーがすべての要求に応じてルビメモリスペースにすべてのユーザーを連れて来るという不必要なコストを支払うことになります。 –

答えて

5

はのparamsを追加[:種子]ページ

+0

リードしてくれてありがとう!可能であれば、どのようにこの作品が説明できますか?私は完全に続くわけではありませんが、まだこの答えを実装する方法は不明です。 – neon

+0

あなたはシードの仕組みをAPIドキュメントで読むことができますhttp://ruby-doc.org/core-1.9.2/Random.html – MikDiet

+0

私はそれを理解しましたが、配列は同じシャッフル順に一貫して表示されます。ユーザーがログアウトしてから戻ると、配列は再シャッフルされるのではなく、最初はシャッフルされた同じ順序にとどまります。奇妙な。 – neon

3

へのすべての雷リンクにKandadaBogguは、上記の指摘するように、Userの全てを取得しますデータベースからのレコードは非効率的です。MySQL's RAND() functionを使用して、の前にランダム化を実行することをお勧めします。シード値をRAND()に渡して、シャッフルがセッションごとに1回だけ行われるようにすることができます。例えば

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をインストールしていないが、これはあなたの元のコードよりも良いを実行する必要があります。

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ので。

関連する問題