Разбивка перемешанного запроса ActiveRecord - PullRequest
5 голосов
/ 01 апреля 2012

Я пытаюсь разбить перетасованный запрос ActiveRecord.Синтаксис для этого с использованием гема Kaminari:

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

Проблема заключается в том, что User.all перетасовывается при каждом запросе на нумерацию страниц, вызывая вызов дублирующихся записей.Есть ли способ предотвратить такое дублирование?

Ответы [ 3 ]

5 голосов
/ 01 апреля 2012

Вам нужно передать seed для ранда между запросами

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 на страницы

3 голосов
/ 13 апреля 2012

Как указывает выше KandadaBoggu, получение всех записей User из базы данных неэффективно, когда вам нужно только 20. Я бы предложил использовать RAND() функцию *1003* MySQL для выполнения рандомизации до вы вернетесь из базы данных.Вы все еще можете передать начальное значение в 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 голосов
/ 28 апреля 2015

Вы также можете сделать это:

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, скорее всего, даст тот же результат, если ваши данные не такие большие.

...