J'ai besoin d'aide, s'il vous plaît. Je suis en train de créer une fonction de recherche avancée pour ma bibliothèque numérique, et je souhaite rechercher des livres par leur nom ou leur description, puis filtrer également les résultats de la recherche par catégorie à laquelle appartiennent les livres.
La base de données est structurée de cette façon: Les livres appartiennent à des sous-catégories et catégories, tandis que les sous-catégories appartiennent uniquement aux catégories. Mais je souhaite filtrer par catégories.
Disons que j'ai un livre intitulé Great Achievers et Great Developers et qu'ils appartiennent au les catégories Achievers et Developers respectivement. Je souhaite que la recherche fonctionne de cette manière: lorsque je recherche à l'aide du mot clé Génial , je verrais les livres Grands succès et Grands développeurs , et quand Je filtre par catégorie Achievers Je ne verrais que Great Achievers .
À l'heure actuelle, ma fonction de recherche avancée peut rechercher des livres par leur nom et leur description, mais ne peut pas filtrer les livres par catégorie dans les résultats de recherche.
Ceci est le code pour le modèle de livre
<%= form_tag(books_path, method: :get) do %> <%= text_field_tag :keywords, params[:keywords] %> <%= collection_select :category, :id, Category.all.order('name ASC'), :id, :name,{include_blank: 'Select Category'} %> <%= submit_tag 'Search', name: nil %> <% end %>
Ceci est le code pour le modèle de catégorie
class BooksController < ApplicationController def index @books = Book.search(params[:keywords]).paginate(:page => params[:page], :per_page => 9).order('created_at DESC') end private def set_book @book = Book.find(params[:id]) end def book_params params.require(:book).permit(:name, :author, :description, :category_id, :sub_category_id, :new_sub_category_name, :upload, :keywords, :deep_keywords) end end
Ceci est le code pour le modèle de sous-catégorie
XXX
Ceci est le code tronqué pour le contrôleur de livres
class SubCategory < ApplicationRecord has_many :books belongs_to :category, required: false end
Ceci est le code tronqué pour la fonction de recherche sur la vue d'index des livres
class Category < ApplicationRecord has_many :sub_categories has_many :books end
J'ai joint une capture d'écran du journal de ma console lorsqu'une action de recherche est effectuée a>
Veuillez toute forme d'assistance sera très appréciée. Merci.
3 Réponses :
Vous avez besoin d'une jointure (non testée, mais vous avez l'idée):
def index @books = Book.search(params). paginate(page: params[:page], per_page: 9). order('created_at DESC') # You already set order on search end
EDIT:
def self.search(params) books = where(nil) keywords = params.dig(:keywords) if keywords books = books.where("name LIKE ? OR description LIKE ? OR author LIKE ?", "%#{keywords}%", "%#{keywords}%", "%#{keywords}%") end cat_id = params.dig(:category, :id) if cat_id books = books.joins(:category).where(category: {id: cat_id}) end books.order('id DESC') end
Merci beaucoup pour votre réponse. Dois-je apporter des modifications à mon contrôleur de livres et à ma fonction de recherche de vue index des livres pour qu'ils fonctionnent correctement?
Salut @CAmador, je viens de l'essayer, voici l'erreur que j'ai rencontrée: ActiveRecord :: StatementInvalid in Books # index SQLite3 :: SQLException: nom de colonne ambigu: nom: SELECT "books". * FROM "books" INNER JOIN "categories" ON "categories". "id" = "books". "category_id" WHERE (nom COMME '% soins infirmiers%' OU description COMME '% soins infirmiers%' OU auteur COMME '% soins infirmiers%') ET "catégorie". "Id" =? ORDER BY id DESC, created_at DESC LIMIT? DÉCALAGE ?. Comment résoudre ce problème?
La meilleure chose à faire est de trouver les livres qui sont dans la catégorie de filtre. Filtrez ensuite cette collection de livres en fonction du terme de recherche.
Vous pouvez modifier le code du contrôleur de livres comme ci-dessous.
class Book < ApplicationRecord has_one_attached :upload belongs_to :category, required: false belongs_to :sub_category, required: false def self.search(keywords) if keywords where("name LIKE ? OR description LIKE ? OR author LIKE ?", "%#{keywords}%", "%#{keywords}%", "%#{keywords}%").order('id DESC') else order('id DESC') end end end
Le code tronqué de la fonction de recherche dans la vue d'index des livres peut rester le même
<%= form_tag(books_path, method: :get) do %> <%= text_field_tag :keywords, params[:keywords] %> <%= collection_select :category, :id, Category.all.order('name ASC'), :id, :name,{include_blank: 'Select Category'} %> <%= submit_tag 'Search', name: nil %> <% end %>
Le code du modèle de livre peut également rester le même
def index if params['category'].blank? or params['category']['id'].blank? @books = Book.all else category = Category.find(params['category']['id']) @books = category.books end @books = @books.search(params[:keywords]).paginate(:page => params[:page], :per_page => 9).order('created_at DESC') end
J'espère que cela vous aidera.
Évaluer cette réponse comme utile si cela peut vous aider, ou commentez la réponse ci-dessous pour plus de précisions .
Merci beaucoup pour votre réponse. Dois-je apporter des modifications à mon modèle de livre et à mon index de livres fonction de recherche de vue pour permettre de fonctionner correctement?
@PromisePreston, pas besoin de changer quoi que ce soit dans le fichier de modèle de livre. Mettez simplement à jour la méthode d'index à laquelle j'ai répondu dans le contrôleur de livres. Cela devrait fonctionner correctement. Veuillez vérifier.
Salut @dharmesh et @CAmador, je viens d'essayer cette réponse mais j'obtiens cette erreur. NoMethodError dans BooksController # index . 'méthode undefined `recherche' pour #
@PromisePreston, Je viens de tester votre exemple dans mon exemple d'application. Pas besoin de changer quoi que ce soit dans le modèle de livre. La fonction de recherche doit rester la même dans la question. Mettez simplement à jour le contrôleur de livre et essayez cette réponse et acceptez la réponse si cela fonctionne correctement.
Salut @dharmesh, je viens de l'essayer maintenant et cela a fonctionné, mais les résultats de la recherche ne filtrent pas encore par catégorie. Il affiche simplement la recherche de livres en fonction de leurs noms, description et auteur sans filtrer les résultats des livres lorsque je sélectionne une catégorie particulière lors de la recherche. Pouvez-vous m'aider s'il vous plaît. Merci.
@PromisePreston Pouvez-vous s'il vous plaît me faire savoir la valeur des paramètres qui est enregistrée dans le journal / console du serveur de rails lors de l'appel?
@dharmesh, je viens de joindre une capture d'écran du journal de la console à la question
@PromisePreston, mise à jour de la condition if dans la réponse. Cela fonctionnerait.
continuons cette discussion dans le chat .
@dharmesh, je rencontre toujours des problèmes avec le filtrage des catégories. Merci beaucoup pour votre aide, je vais continuer cette discussion en chat.
La recherche est quelque chose que vous pouvez éviter de faire par vous-même si vous utilisez ransack . Vous pouvez même faire un one-liner dans votre contrôleur avec lui pour obtenir ce que vous voulez:
#params[:q] for books with category_id == 10 { "category_id_eq": 10 } #params[:q] for books with name or description or author matching "search" { "name_or_description_or_author_matches": "%search%" } #params[:q] for books with name or description or author matching "search" and category_id == 10 { "name_or_description_or_author_matches": "%search%", "category_id_eq": 10 } #params[:q] for books with name or description or author matching "search" and category_id == 10, ordered by created_at { "name_or_description_or_author_matches": "%search%", "category_id_eq": 10, "s": "created_at desc" }
Ensuite, dans vos requêtes, vous devez passer les paramètres [: q]
, en effectuant la recherche dont vous avez besoin pour la ressource livres. IE:
def index @books = Book.all.ransack(params[:q]).results.paginate(:page => params[:page], :per_page => 9) end
Vérifiez le correspondants disponibles pour que vous puissiez créer vos filtres comme vous le souhaitez.