Rails 3, will_paginate, aleatório, repetição de registros, Postgres, falha de setseed

Eu tenho um banco de dados de filmes com atributos. Gostaria de retornar um lote consultado desses filmes em ordem aleatória para um modelo com paginação. Estou usando o will_paginate. Eu tentei o seguinte:

<code>## MoviesController

movies = Movie.get_movies(query_string)   # a method in Movie model that takes in 
                                          # a query_string and fetches movies 
                                          # with user-set params

@movies = movies.order('random()').page(params[:page]).per_page(16)
</code>

Isso funciona bem, exceto que os filmes são repetidos de uma página para outra. Soluções para este problema foram postadasAqui eAqui. Essas ligações explicam que, porque oaleatória() semente é reposta de página para página, não há consistência eOFFSET é inútil. Eles oferecem ótimas soluções para usuários do MySQL,rand (n) função leva uma sementen. O Postgres, no entanto, não faz isso. Você tem que declararsetseed (n) emSELECIONAR antes de emitiraleatória() emORDEM.

Então eu tentei o caminho postgres para definir a semente:

<code>@movies = movies.select('setseed(.5)').order('random()').page(params[:page]).per_page(16)
</code>

Curiosamente, isso retornou objetos Movie com absolutamente nenhum atributo. O seguinte foi levantado do modelo:

ActiveModel :: MissingAttributeError in Movies # action

atributo ausente: some_movie_attribute

Depurei isso e, assim que a pilha atingiu o action_controller / metal, o @movies continha:

[#<Movie >, #<Movie >, #<Movie >, #<Movie >, #<Movie >, #<Movie >, #<Movie >, #<Movie >, #<Movie >, #<Movie >, #<Movie >, #<Movie >, #<Movie >, #<Movie >, #<Movie >, #<Movie >]

Esse número de objetos Movie (18) corresponde ao número de filmes retornados da consulta.

Eu também tentei o seguinte para ver sesetseed (n) foi o problema ao remover o método de ordem aleatória:

<code>@movies = movies.select('setseed(.5)').page(params[:page]).per_page(16)
</code>

Isso retornou os mesmos objetos Movie que não são de atributos, conforme mostrado acima. Então parece quesetseed (n) é realmente o problema.

Eu tentei algumas soluções alternativas, como:

<code># MoviesController

movies = Movie.get_movies(query_string)
shuf_movs = movies.shuffle  ## effectively turns shuf_movs into an array

@movies = shuf_movs.paginate(:page => params[:page], :per_page => 16)
</code>

Isso também retornou páginas com filmes repetidos. Eu pensei que isso era porque paginação precisava dos objetos a serem ordenados poralguma coisa, e você não pode definir sementes no Array # shuffle. Então, tentei escrever meu próprio código de randomização que armazenaria temporariamente um id a ser ordenado nos objetos Movie. (Por favor, desculpe o código desleixado):

<code># Movie model

attr_accessor :rand_id

# MoviesController

movies = get_movies(query_string)
movies_count = movies.count
r = Random.new
nums = []
rand_movs = []
id = 1
while nums.count != movies_count
  num = r.rand(0..movies_count - 1)
  if !(nums.include?(num))
    movie = movies[num]
    movie.rand_id = id
    rand_movs << movie
    nums      << num
    id += 1
  end
end

@movies = rand_movs.sort_by { |a| a.rand_id }.paginate(:page => params[:page], :per_page => 16)
</code>

Isso ainda produziu repetindo filmes em diferentes páginas. Neste ponto, percebo que o will_paginate não aceita o que você classificou antespaginar é chamado. Então eu tentei isso:

<code>@movies = rand_movs.paginate(:order => 'rand_id', :page => params[:page], :per_page => 16)
</code>

Isso ainda repete registros.: order -> 'rand_id' é ignorado porque:ordem só importa quando você está lidando com objetos ActiveRecord, não matrizes.

assimsetseed (n) parece ser minha única esperança para obter registros não repetidos randomizados usando will_paginate. Alguma ideia?

Obrigado!

questionAnswers(2)

yourAnswerToTheQuestion