Paginez dans une liste aléatoire de billets de blog en utilisant will_paginate
-
03-07-2019 - |
Question
Je souhaite donner aux utilisateurs la possibilité de parcourir les articles de mon blog dans un ordre aléatoire.
Je ne peux pas l'implémenter comme ceci:
@posts = Post.paginate :page => params[:page], :order => 'RANDOM()'
étant donné que le paramètre :order
est appelé à chaque requête, je risque donc de répéter les articles du blog.
Quelle est la meilleure façon de faire cela?
La solution
RAND accepte une graine dans MySQL:
RAND(N)
Extrait du documentation MySQL :
RAND (), RAND (N)
Retourne une valeur à virgule flottante aléatoire v dans la plage 0 < = v < 1,0. Si un l'argument entier constant N est spécifié, il est utilisé comme graine valeur, qui produit un répétable séquence de valeurs de colonne. dans le Dans l'exemple suivant, notez que les séquences de valeurs produites par RAND (3) sont identiques aux deux endroits où elles se produisent.
Les autres bases de données devraient avoir des fonctionnalités similaires.
Si vous utilisez la valeur de départ SAME à chaque fois que vous appelez RAND, l'ordre sera cohérent pour toutes les demandes et vous pourrez effectuer une pagination en conséquence.
Vous pouvez ensuite stocker la graine dans la session de l'utilisateur. Ainsi, chaque utilisateur obtiendra un ensemble de résultats qui lui est propre.
Autres conseils
Pour éviter que chaque page (générée à partir d'une nouvelle demande) ait potentiellement une publication répétée, vous devez stocker l'ordre des publications quelque part pour pouvoir les récupérer sur plusieurs requêtes.
Si vous souhaitez que chaque utilisateur ait un ordre aléatoire unique, sauvegardez-le dans un tableau d'identifiants de session.
Si vous ne craignez pas que tous les utilisateurs aient le même ordre aléatoire, placez une colonne de position dans la table des publications.
Vous pourriez: order = > RANDOM () sur votre requête d'origine qui remplit @posts, puis lorsque vous effectuez une pagination, ne spécifiez pas l'ordre.
Créez une portée nommée sur votre modèle Post qui encapsule le comportement aléatoire:
class Post < ActiveRecord::Base
named_scope :random, :order => 'RANDOM()'
.
.
.
end
Votre PostsController
code devient alors:
@posts = Post.random.paginate :page => params[:page]