Paginate through a randomized list of blog posts using will_paginate
Asked Answered
H

4

5

I want to give users the ability to page through my blog posts in random order.

I can't implement it like this:

@posts = Post.paginate :page => params[:page], :order => 'RANDOM()'

since the :order parameter is called with every query, and therefore I risk repeating blog posts.

What's the best way to do this?

Hotien answered 1/5, 2009 at 5:10 Comment(0)
D
3

RAND accepts a seed in MySQL:

RAND(N) 

From the MySQL docs:

RAND(), RAND(N)

Returns a random floating-point value v in the range 0 <= v < 1.0. If a constant integer argument N is specified, it is used as the seed value, which produces a repeatable sequence of column values. In the following example, note that the sequences of values produced by RAND(3) is the same both places where it occurs.

Other databases should have similar functionality.

If you use the SAME seed each time you call RAND, the order will be consistent across requests and you can paginate accordingly.

You can then store the seed in the user's session - so each user will see a set of results unique to them.

Delibes answered 6/5, 2009 at 2:13 Comment(2)
What's the syntax for using RANDOM() with a seed? I can't find it.Hotien
Added syntax details for MySQLDelibes
C
1

To avoid each page (generated from a new request) potentially having a repeated post you'll need to store the order of posts somewhere for retrieval over multiple requests.

If you want each user to have a unique random order then save the order in a session array of IDs.

If you don't mind all users having the same random order then have a position column in the posts table.

Carborundum answered 2/5, 2009 at 7:37 Comment(0)
H
0

You could :order => RANDOM() on your original query that populates @posts, and then when you paginate, don't specify the order.

Hilaire answered 1/5, 2009 at 15:41 Comment(0)
I
-2

Create a named scope on your Post model that encapsulates the random behaviour:

class Post < ActiveRecord::Base
  named_scope :random, :order => 'RANDOM()'
  .
  .
  .
end

Your PostsController code then becomes:

@posts = Post.random.paginate :page => params[:page]
Iatric answered 1/5, 2009 at 15:52 Comment(1)
This won't work -- you'll get a random 30 (or however big your page size is) posts every time.Hotien

© 2022 - 2024 — McMap. All rights reserved.