Paginate modèles multiples dans Kaminari
-
26-10-2019 - |
Question
Je crée une page de recherche qui va faire une demande de recherche large sur les utilisateurs, les messages et les commentaires. J'ai actuellement:
# POST /search
def index
query = params[:query]
@users = User.search(query).page(params[:page])
@posts = Post.search(query).page(params[:page])
@comments = Comment.search(query).page(params[:page])
respond_to do |format|
format.html
end
end
Cependant, je suis vraiment essayer d'obtenir quelque chose où tous les résultats sont mélangés puis paginés. Quelles sont quelques-unes des stratégies pour faire la recherche paginé comme ça? Merci!
La solution
Avant de penser à une solution, vous devez d'abord définir exactement ce que vous voulez que le résultat final soit. Si vous souhaitez afficher quelques de chaque type d'enregistrement sur la page de résultats, vous pouvez modifier l'approche que vous Affichée et combiner les trois résultats paginés en utilisant:
@results = @users + @posts + @comments
@results.sort! { |a, b| a.score(query) > b.score(query) }
Chaque objet devra avoir « score » une méthode d'instance qui laisser tri en fonction des priorités de la requête. , Vous devrez également modifier votre point de vue de gérer un rendu correct de chaque élément et faire en sorte que la pagination est appelée sur le modèle avec plus de pages.
Alternativement, une méthode plus robuste serait d'ajouter un service de recherche en texte intégral (tels que Tank Index , < a href = "http://websolr.com/" rel = "nofollow"> Web Solr, Thinking Sphinx ). La technologie pour ce qui est chaud pour ces mouvements rapidement, afin de faire des recherches et trouver celui qui correspond à vos besoins. Exemple de syntaxe pour ce serait quelque chose comme:
User.multi_solr_search query, models: [Post, Comment]
Autres conseils
Depuis ce commit: https://github.com/amatsuda/kaminari/commit/f9f529fb68ab89feea38773a4c625c1b14859128
Vous pouvez effectuer les opérations suivantes
À votre avis, vous pouvez faire ceci:
<%= paginate @users, :remote => true, :param_name => "user_page" %>
<%= paginate @posts, :remote => true, :param_name => "post_page" %>
<%= paginate @comments, :remote => true, :param_name => "comment_#{some_post_id}_page" %>
puis dans votre contrôleur, vous pouvez les consulter de cette façon:
@users = User.search(query).page(params[:user_page])
@posts = Post.search(query).page(params[:post_page])
@comments = Comment.search(query).page(params[:comment_page])
et la js.erb de votre point de vue que vous pourriez avoir quelque chose comme:
$('#posts').html('<%= escape_javascript render(@posts) %>');
$('.table-pager').html('<%= escape_javascript(paginate(@posts, :remote => true).to_s) %>');
Vous pouvez combiner les résultats de la page de requête et exécuter sur ce point.
users = User.search(query)
posts = Post.search(query)
comments = Comment.search(query)
@results = users + posts + comments
@results.page(params[:page])