Rails 3, will_paginate, random, duplicate entries, Postgres, dialing failure

I have a movie database with attributes. I would like to return the requested batch of these films in random order to a paginated template. I am using will_paginate. I tried the following:

## 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)

This works well, except that movies are repeated from page to page. Solutions to this problem have been published here and here . These links explain this because random () contains a reset from page to page, there is no consistency, and OFFSET is useless. They offer great solutions for MySQL users, as the rand (n) function takes up the n seed . However, Postgres does not. You must declare setseed (n) in SELECT before releasing random () in ORDER .

So, I tried the postgres way to set the seed:

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

, Movie . :

ActiveModel:: MissingAttributeError #

: some_movie_attribute

, action_controller/metal, @movies :

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

Movie (18) , .

, , setseed (n), :

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

, , . , , setseed (n).

, :

# 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)

. , , , , # shuffle. , , Movie. (, ):

# 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)

. , will_paginate , , paginate. :

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

. : order β†’ 'rand_id' , : , ActiveRecord, .

setseed (n) will_paginate. ?

!

+5
2

postgres, ...

Movie.connection.execute "select setseed(0.5)"
Movie.where(...).order('random()').page(params[:page]).per_page(15)

Array#shuffle , Kernel.rand, Kernel.srand

+18

select:

@movies = movies.select(['setseed(.5)', 'some_movie_attribute']).order('random()').page(params[:page]).per_page(16)

some_movie_attribute, , . .

+1

All Articles