Rails: фильтрация поиска - PullRequest
0 голосов
/ 10 июня 2019

Пожалуйста, мне нужна помощь для проекта цифровой библиотеки, над которым я работаю.Я хочу добавить в приложение некоторые функции фильтрации поиска.

Приложение в основном содержит книги, относящиеся к подкатегориям, и подкатегории, относящиеся к категориям.

Я хочу создатьфункция фильтрации поиска, где вы можете фильтровать книги по их категориям при поиске конкретной книги.

Итак, сначала вы создаете категории, а затем вы создаете подкатегории и выбираете категории, к которым относятся эти подкатегории, изатем вы создаете книги и выбираете только те подкатегории, к которым относится каждая книга, что автоматически помещает эту книгу в категорию, к которой относится эта подкатегория.

На данный момент поисковые фильтры работают, только если я добавляю категории в книгиновая форма.То есть, если я изменю новую форму книги, а затем включу выбор формы в форму.Но я просто хочу включить в новую форму книги только подкатегории, поскольку каждая подкатегория уже принадлежит категории.

Коды следующие:

Модель книги

class Book < ApplicationRecord
  belongs_to :category, required: false
  belongs_to :subcategory, required: false

  def self.search(keywords)
    if keywords
      where('name LIKE ? OR description LIKE ? OR author LIKE ? OR abstract LIKE ?', "%#{keywords}%", "%#{keywords}%", "%#{keywords}%", "%#{keywords}%").order('id DESC')
    else
      order('id DESC')
    end
  end
end

Модель подкатегории

class Subcategory < ApplicationRecord
  belongs_to :category
  has_many :books
end

Категория Модель

class Category < ApplicationRecord
  has_many :subcategories
  has_many :books
end

Контроллер книг (усеченный))

class BooksController < ApplicationController
  before_action :set_book, only: [:show, :edit, :update, :destroy]

  def index
    if params[:category].blank? or params[:category][:id].blank? 
      @books_view = Book.all
    else  
      @books_view = Category.find(params[:category][:id]).books
    end
    @books = @books_view.search(params[:keywords]).paginate(page: params[:page], per_page: 12)
  end
end

Книга указателей Страница для поиска

<%= form_tag(books_path, method: :get) do %>
      <%= text_field_tag :keywords, params[:keywords], {placeholder: 'eg: Nursing', :class => 'searchForm'} %>
      <%= collection_select :category, :id, Category.all.order('name ASC'), :id, :name,{include_blank: 'Select Category'}, { :class => 'form-control'} %>
    <button type="submit">
      Search
      <%= image_tag("searchIcon.svg", :alt => "search", :class => "") %>
    </button>
  <% end %>

Пожалуйста, мне нужна помощь.Это будет высоко оценено.Спасибо.

Обновление

Я пробовал решение из Dileep Nandanam , обновив таким образом Контроллер книг таким образом

class BooksController < ApplicationController
    before_action :set_book, only: [:show, :edit, :update, :destroy]

    def index
        if params[:category].blank? or params[:category][:id].blank? 
            @books_view = Book.all
        else  
            @books_view = Book.joins(:subcatagory).joins('catagories on catagories.id = subcatagories.catagory_id').where(catagories: {id: params[:catagory][:id]})
        end
        @books = @books_view.search(params[:keywords]).paginate(page: params[:page], per_page: 12)
    end
end 

Но это действительно не сработало, как ожидалось.Я столкнулся с некоторыми проблемами.Ниже приведен скриншот проблемы.

! [NoMethodError в BooksController # index undefined метод `[] 'для nil: NilClass] 1

Ответы [ 2 ]

0 голосов
/ 10 июня 2019

Строго соблюдайте правила хранения category_id в подкатегориях и subcatagory_id в книгах, но не в catagory_id в книгах.

Таким образом, мы слегка модифицируем действие индекса

class BooksController < ApplicationController
    before_action :set_book, only: [:show, :edit, :update, :destroy]

    def index
        if params[:category].blank? or params[:category][:id].blank? 
            @books_view = Book.all
        else  
            @books_view = Book.joins(:subcatagory).joins('catagories on catagories.id = subcatagories.catagory_id').where(catagories: {id: params[:catagory][:id]})
        end
        @books = @books_view.search(params[:keywords]).paginate(page: params[:page], per_page: 12)
    end
end

и метод поиска становится

def self.search(keywords)
    if keywords
        where('books.name LIKE ? OR book.description LIKE ? OR book.author LIKE ? OR book.abstract LIKE ?', "%#{keywords}%", "%#{keywords}%", "%#{keywords}%", "%#{keywords}%").order('books.id DESC')
    else
        order('books.id DESC')
    end
end
0 голосов
/ 10 июня 2019

Я полагаю, что ваши проблемы проистекают из этой конкретной вещи:

class Book < ApplicationRecord
  belongs_to :category, required: false # <= This is wrong
  belongs_to :subcategory, required: false
end

Ответ на ваш конкретный вопрос:

<%= form_tag(books_path, method: :get) do %>
      <%= text_field_tag :keywords, params[:keywords], {placeholder: 'eg: Nursing', :class => 'searchForm'} %>
      <%= collection_select :subcategory, :id, Subcategory.all.order('name ASC'), :id, :name,{include_blank: 'Select Category'}, { :class => 'form-control'} %>
    <button type="submit">
      Search
      <%= image_tag("searchIcon.svg", :alt => "search", :class => "") %>
    </button>
  <% end %>

Но давайте уточним ответ:

Слушай, в твоей абстракции есть большая проблема.Если книга принадлежит как подкатегории (с subcategory_id), так и к категории (с category_id), у вас действительно нет согласованной структуры данных.Если вы используете реляционную базу данных, вы нарушаете нормализацию БД.То, что действительно должно произойти здесь, это разделить Категорию от Книги и ссылаться на нее через Подкатегорию, как это:

class Book < ApplicationRecord
  belongs_to :category, required: false, through: :subcategory
  belongs_to :subcategory, required: false
end
...