Ruby on Rails - 根据用户选择的选项过滤记录
Ruby on Rails - Filter records based on users selected options
在我的应用程序中,我有一个 Book
模型。我的数据库中有大约 10000k 本书记录。基本上,该应用程序的工作原理是用户可以 select 选项 并获取与他们插入的凭据 匹配 的图书列表。
每个 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
到 filter 书中所做的:
@book_filter = Book
.where(type: @book.type)
.where(language: @book.language)
.where(genres: @book.genres)
这工作得很好,但我遇到了一些问题。例如,如果用户没有 select 任何 书籍类型/ type
或任何其他选项,而不是 all
,我得到 nil
因此,不会向用户显示任何书籍。
我的想法是,如果选项未被 selected,则该选项的 where
不会 受到影响 或它通过 all
.
我试过了,但没有成功:
@book_filter = Book
.where(type: @book.type || '')
.where(language: @book.language || '')
.where(genres: @book.genres || '')
我的第二个问题是我觉得过滤器可以写得更聪明 & Rails .
在此先致谢,如有任何帮助,我们将不胜感激!
Rails 5.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
在您的 model
中包含 module
,如下所示:
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:请记住变量或模型与问题不同,但解决方案是可以对任何应用程序实施的通用解决方案。
基于 但将 public_send
替换为 where
对我有用。 Rails5
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
在我的应用程序中,我有一个 Book
模型。我的数据库中有大约 10000k 本书记录。基本上,该应用程序的工作原理是用户可以 select 选项 并获取与他们插入的凭据 匹配 的图书列表。
每个 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
到 filter 书中所做的:
@book_filter = Book
.where(type: @book.type)
.where(language: @book.language)
.where(genres: @book.genres)
这工作得很好,但我遇到了一些问题。例如,如果用户没有 select 任何 书籍类型/ type
或任何其他选项,而不是 all
,我得到 nil
因此,不会向用户显示任何书籍。
我的想法是,如果选项未被 selected,则该选项的 where
不会 受到影响 或它通过 all
.
我试过了,但没有成功:
@book_filter = Book
.where(type: @book.type || '')
.where(language: @book.language || '')
.where(genres: @book.genres || '')
我的第二个问题是我觉得过滤器可以写得更聪明 & Rails .
在此先致谢,如有任何帮助,我们将不胜感激!
Rails 5.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
在您的 model
中包含 module
,如下所示:
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:请记住变量或模型与问题不同,但解决方案是可以对任何应用程序实施的通用解决方案。
基于 public_send
替换为 where
对我有用。 Rails5
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