在我的应用程序中,我有一个Book
模型。我的数据库中大约有10000k图书记录。基本上,该应用程序的工作方式是用户可以选择选项并获取与它们插入的证书匹配匹配的图书列表。
这些books
中的每个都有type
,language
和genres
。
每本书可以有多个type
,language
和genres
(就像一个数组)
title: 'Have fun book'
type: ['pdf', 'paper', 'website']
language: ['Egnlish', 'French', 'German', 'Spanish']
genres: ['comedy']
我的BooksController
:
def book_params
params.require(:book).permit(type:[], language:[], genres:[])
end
用户可以在其中插入其凭据并过滤书籍的表格如下图所示:
目前,这是我在BooksController
中要执行的操作,以过滤这些书:
@book_filter = Book
.where(type: @book.type)
.where(language: @book.language)
.where(genres: @book.genres)
这很好,但是我有一些问题。例如,如果用户未选择任何图书类型/ type
或其他任何选项,则不会得到all
,而是得到nil
原因,不会向用户显示任何图书。
我要记住的是,如果未选择该选项,则该选项的where
不会受到影响或会通过all
。
我没有运气尝试过这个
@book_filter = Book
.where(type: @book.type || '')
.where(language: @book.language || '')
.where(genres: @book.genres || '')
我的第二个问题是,我认为过滤器可以写得更聪明,并且采用 Rails方式。
提前感谢,感谢您的帮助!
Rails 5.1
答案 0 :(得分:1)
在您的models/concerns
中创建一个module
:
module Filterable
extend ActiveSupport::Concern
module ClassMethods
def filter(filtering_params)
results = self.where(nil)
filtering_params.each do |key, value|
results = results.public_send(key, value) if value.present?
end
results
end
end
end
将module
放入您的model
中,如下所示:
class Product
include Filterable
...
end
然后在您的控制器中执行以下操作:
@products = Product.filter(params.slice(:status, :location, :starts_with))
私人
# A list of the param names that can be used for filtering the Product list
def filtering_params(params)
params.slice(:status, :location, :starts_with)
end
module
背后的原因是因为此代码可重复使用,并且可以在应用程序的任何部分使用。
PS:请记住,变量或模型与问题不相同,但解决方案是可以对任何应用程序实施的通用解决方案。
答案 1 :(得分:0)
基于https://stackoverflow.com/a/54401841/3058437,但将public_send
替换为where
对我来说很有效。 Rails 5
module Filterable
extend ActiveSupport::Concern
module ClassMethods
def filter(filtering_params)
results = self.where(nil)
filtering_params.each do |key, value|
results = results.where("#{key} = ?", value) if value.present?
end
results
end
end
end