2012-04-01 56 views
5

我正在嘗試分頁洗牌ActiveRecord查詢。這樣做使用雷寶石的語法是:分頁洗牌ActiveRecord查詢

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

的問題與此是User.all重新洗牌每個分頁請求,導致被稱爲重複的記錄。有什麼辦法可以防止這種重複?

+1

調用'User.all'會導致服務器顯着減速。即使你只有100個用戶,你也會支付在每次請求中將所有用戶帶到ruby內存空間的不必要花費。 – 2012-04-09 02:40:21

回答

5

您需要將種子蘭特查詢之間

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

並在視圖中添加PARAMS [:種子]所有雷鏈接

+0

感謝您的帶頭人!如果可能的話,你能解釋這是如何工作的嗎?我沒有完全遵循,仍然不確定如何實現這個答案。 – neon 2012-04-02 04:41:43

+0

你可以閱讀API文檔如何種子作品http://ruby-doc.org/core-1.9.2/Random.html – MikDiet 2012-04-02 05:27:36

+0

我想到了,但現在陣列出現在相同的洗牌順序 - 意味着即使在用戶註銷並返回,陣列保持原先的洗牌順序,而不是重新洗牌。奇怪。 – neon 2012-04-02 16:27:50

3

頁作爲KandadaBoggu上面所指出的,檢索所有User的當您僅需要20時,數據庫中的記錄效率低下。我建議使用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安裝要測試的,但這應該執行比你原來的代碼更好。

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,如果你的數據不是很大會產生很可能是相同的結果。