我有一个具有属性的电影数据库。我想按照随机顺序将这些电影的一批查询返回到带有分页的模板。我正在使用will_paginate。我尝试了以下方法:Rails 3,will_paginate,随机,重复记录,Postgres,setseed失败
## 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)
这个效果很好,除了电影在页面之间重复。此问题的解决方案已发布here和here。这些链接解释说,因为随机()种子每页重置一次,所以没有一致性,并且OFFSET变得无用。它们为MySQL用户提供了很好的解决方案,因为其rand(n)函数需要种子n。 Postgres,但是,不这样做。您必须声明setseed(n)在选择发行前随机()在令。
所以,我想Postgres的方式来设置种子:
@movies = movies.select('setseed(.5)').order('random()').page(params[:page]).per_page(16)
奇怪的是,这回电影,绝对没有属性的对象。下面是从模板中提出:
::加载ActiveModel在MissingAttributeError电影#行动
缺少的属性:some_movie_attribute
我调试此,一旦堆达到action_controller/metal,@movies contains:
[#<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)
此返回的相同非属性Movie对象如上奠定了。所以看起来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)
这也返回了重复电影的网页。我以为这是因为分页需要通过订购的对象,并且您无法在Array#shuffle中设置种子。所以我试着写我自己的随机代码,它会临时存储一个要在Movie对象中排序的ID。 (请原谅sl 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)
这仍然在不同的页面上产生重复的电影。在这一点上,我意识到will_paginate不会在分页被调用之前排序。所以我试过这个:
@movies = rand_movs.paginate(:order => 'rand_id', :page => params[:page], :per_page => 16)
那还是重复记录。 :order - >'rand_id'被忽略,因为:order只在处理ActiveRecord对象而不是数组时处理。
所以setseed(n)似乎是我使用will_paginate实现随机化非重复记录的唯一希望。有任何想法吗?
谢谢!
种子它选择指定的列在查询中,你指定了none,只有种子。不知道它是否会工作,但试试这个:'.select('*,setseed(1)')' – Matzi 2012-04-28 23:49:48