ユーザーがブログの投稿をランダムな順序でページングできるようにしたいと考えています。
次のように実装することはできません。
@posts = Post.paginate :page => params[:page], :order => 'RANDOM()'
パラメータはすべてのクエリで呼び出されるため:order
、ブログ投稿を繰り返すリスクがあります。
これを行う最善の方法は何ですか?
ユーザーがブログの投稿をランダムな順序でページングできるようにしたいと考えています。
次のように実装することはできません。
@posts = Post.paginate :page => params[:page], :order => 'RANDOM()'
パラメータはすべてのクエリで呼び出されるため:order
、ブログ投稿を繰り返すリスクがあります。
これを行う最善の方法は何ですか?
RAND は MySQL でシードを受け入れます。
RAND(N)
MySQL ドキュメントから:
ランド()、ランド(N)
範囲 0 <= v < 1.0 のランダムな浮動小数点値 v を返します。定数整数引数 N が指定されている場合、それがシード値として使用され、列値の反復可能なシーケンスが生成されます。次の例では、RAND(3) によって生成される値のシーケンスは、発生する場所の両方で同じであることに注意してください。
他のデータベースにも同様の機能が必要です。
RAND を呼び出すたびに同じシードを使用すると、リクエスト全体で順序が一貫し、それに応じてページ付けできます。
その後、シードをユーザーのセッションに保存することができます。これにより、各ユーザーに固有の一連の結果が表示されます。
(新しいリクエストから生成された) 各ページに投稿が繰り返される可能性を回避するには、複数のリクエストで取得できるように、投稿の順序をどこかに保存する必要があります。
各ユーザーに一意のランダムな順序を持たせたい場合は、その順序を ID のセッション配列に保存します。
すべてのユーザーが同じランダムな順序であることを気にしない場合は、posts テーブルに position 列を作成します。
@posts を入力する元のクエリで :order => RANDOM() を実行できます。その後、ページネーションするときに順序を指定しないでください。
ランダムな動作をカプセル化する名前付きスコープを Post モデルに作成します。
class Post < ActiveRecord::Base
named_scope :random, :order => 'RANDOM()'
.
.
.
end
コードは次のPostsController
ようになります。
@posts = Post.random.paginate :page => params[:page]