轨道:搜索筛选



拜托,我需要一些帮助来做我正在从事的数字图书馆项目。我想向应用程序添加一些搜索过滤功能。

该应用程序主要具有属于子类别的书籍和属于类别的子类别。

我想创建一个搜索过滤功能,您可以在搜索特定书籍时根据类别过滤书籍。

因此,首先创建类别,然后创建子类别并选择这些子类别所属的类别,然后创建书籍并仅选择每本书所属的子类别,这会自动将该图书置于该子类别所属的类别中。

目前,仅当我将类别添加到书籍新表单时,搜索过滤器才有效。也就是说,如果我修改书籍新表单,然后在表单中包含类别选择。但我只想在书籍新形式中包含子类别,因为每个子类别都已经属于一个类别。

代码如下

书籍模型

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 in BooksController#index undefined 方法 '[]' for nil:NilClass]1

我相信你的问题来自这个特定的事情:

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

严格将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