Ruby on rails 在Rails中构建一个简单的搜索表单?

Ruby on rails 在Rails中构建一个简单的搜索表单?,ruby-on-rails,ruby,search,activerecord,rails-activerecord,Ruby On Rails,Ruby,Search,Activerecord,Rails Activerecord,我正在尝试用RubyonRails构建一个简单的搜索表单,我的表单非常简单,基本上你可以从一系列选项中选择字段,然后显示与字段匹配的所有事件。当我将任何字段留空时,问题就出现了 下面是负责过滤参数的代码 Event.joins(:eventdates).joins(:categories).where ("eventdates.start_date = ? AND city = ? AND categories.name = ?", params[:event][:date], params[

我正在尝试用RubyonRails构建一个简单的搜索表单,我的表单非常简单,基本上你可以从一系列选项中选择字段,然后显示与字段匹配的所有事件。当我将任何字段留空时,问题就出现了

下面是负责过滤参数的代码

Event.joins(:eventdates).joins(:categories).where
("eventdates.start_date = ? AND city = ? AND categories.name = ?", 
params[:event][:date], params[:event][:city], params[:event][:category]).all
从我得到的情况来看,它会查找任何字段为空的事件,但由于所有字段都不是空的,除非所有3个字段都已填充,否则它不会匹配,当我试图说,查看日期范围或数组中的事件时,另一个问题出现了,我不知道如何在搜索中度过多天


一般来说,我对制作搜索表单非常陌生,所以我甚至不知道这是否是最好的方法,而且我正在尝试在不需要特殊模型的情况下保留搜索。

下面可能就是您想要的。注意:如果所有字段均为空,则显示事件表中可与eventdates和categories链接的所有数据

events = Event.joins(:eventdates).joins(:categories)
if params[:event]
  # includes below where condition to query only if params[:event][:date] has a value
  events = events.where("eventdates.start_date = ?", params[:event][:date]) if params[:event][:date].present?
  # includes below where condition to query only if params[:event][:city] has a value
  events = events.where("city = ?", params[:event][:city]) if params[:event][:city].present?
  # includes below where condition to query only if params[:event][:city] has a value
  events = events.where("categories.name = ?", params[:event][:category]) if params[:event][:category].present?
end
要使用多天进行搜索,请执行以下操作:

# params[:event][:dates] is expected to be array of dates. 
# Below query gets converted into an 'IN' operation in SQL, something like "where eventdates.start_date IN ['date1', 'date2']"
events = events.where("eventdates.start_date = ?", params[:event][:dates]) if params[:event][:dates].present?

下面可能是你正在寻找的。注意:如果所有字段均为空,则显示事件表中可与eventdates和categories链接的所有数据

events = Event.joins(:eventdates).joins(:categories)
if params[:event]
  # includes below where condition to query only if params[:event][:date] has a value
  events = events.where("eventdates.start_date = ?", params[:event][:date]) if params[:event][:date].present?
  # includes below where condition to query only if params[:event][:city] has a value
  events = events.where("city = ?", params[:event][:city]) if params[:event][:city].present?
  # includes below where condition to query only if params[:event][:city] has a value
  events = events.where("categories.name = ?", params[:event][:category]) if params[:event][:category].present?
end
要使用多天进行搜索,请执行以下操作:

# params[:event][:dates] is expected to be array of dates. 
# Below query gets converted into an 'IN' operation in SQL, something like "where eventdates.start_date IN ['date1', 'date2']"
events = events.where("eventdates.start_date = ?", params[:event][:dates]) if params[:event][:dates].present?
这将更加容易和优化。如果您使用关注点来过滤数据

在模型中提出一个问题

filterable.rb

module Filterable
  extend ActiveSupport::Concern

  module ClassMethods
    def filter(filtering_params)
     results = self.where(nil)
     filtering_params.each do |key, value|
       if column_type(key) == :date || column_type(key) == 
       :datetime
         results = results.where("DATE(#{column(key)}) = ?", 
         Date.strptime(value, "%m/%d/%Y")) if 
         value.present?  
       else
         results = results.where("#{column(key)} Like ? ", "%#{value}%") if 
         value.present?
       end
     end
     results
    end

   def resource_name
    self.table_name
   end

   def column(key)
    return key if key.split(".").count > 1
    return "#{resource_name}.#{key}"
   end

   def column_type(key)
    self.columns_hash[key].type
   end
  end
end
在要筛选的模型文件中包含此问题

Model.rb

 include Filterable
在控制器中添加此方法

def search
    @resources = Model.filter(class_search_params)
    render 'index'
end


def class_search_params
    params.slice(:id,:name) #Your field names
end
因此,这是一个全球性的解决方案。您不需要使用查询进行筛选。只需在模型文件中添加此关注点。 就是这样。

它将更加简单和优化。如果您使用关注点来过滤数据

在模型中提出一个问题

filterable.rb

module Filterable
  extend ActiveSupport::Concern

  module ClassMethods
    def filter(filtering_params)
     results = self.where(nil)
     filtering_params.each do |key, value|
       if column_type(key) == :date || column_type(key) == 
       :datetime
         results = results.where("DATE(#{column(key)}) = ?", 
         Date.strptime(value, "%m/%d/%Y")) if 
         value.present?  
       else
         results = results.where("#{column(key)} Like ? ", "%#{value}%") if 
         value.present?
       end
     end
     results
    end

   def resource_name
    self.table_name
   end

   def column(key)
    return key if key.split(".").count > 1
    return "#{resource_name}.#{key}"
   end

   def column_type(key)
    self.columns_hash[key].type
   end
  end
end
在要筛选的模型文件中包含此问题

Model.rb

 include Filterable
在控制器中添加此方法

def search
    @resources = Model.filter(class_search_params)
    render 'index'
end


def class_search_params
    params.slice(:id,:name) #Your field names
end
因此,这是一个全球性的解决方案。您不需要使用查询进行筛选。只需在模型文件中添加此关注点。
就是这样。

我在实现这个解决方案时遇到了问题,无论我通过搜索方法发送的输入是什么,它都会返回所有可能的事件,即使保留为空,即使我的表单像f.text\u field:name一样简单,所以我不知道我做错了什么。@Bluespheal你做了搜索路线了吗?如果是,则只在筛选方法中输入exit。你可以在那里扔垃圾。你的关键和价值是什么。关键和价值是最重要的!如果您仍然面临问题,请告诉我。是的,我有搜索路线和索引视图,问题是列出了所有可能的事件我既看不到关键字也看不到值,我看到的唯一参数是城市:,日期:和类别:所有内部事件可能我遗漏了什么,最让我困惑的是如何处理键和值。@Bluespheal键是您要筛选的字段名,值是您为搜索输入的字段的值。e、 g.在文本字段名称中输入test并进行搜索。。然后名称变成键,值变成测试。明白了吗?哦!现在我明白了,我仍然无法过滤日期:“2017-06-30”,城市:Tulum,类别:Cultura,但所有事件都使用@resources.each do | event |列出。我觉得我遗漏了一些明显的东西……我在实现此解决方案时遇到了问题,无论我通过搜索方法发送的输入是什么,它都会返回所有可能的事件,即使留空,即使我的表单像f.text_field:name一样简单,我也不知道我做错了什么。@Bluespheal你做了搜索路线了吗?如果是,则只在筛选方法中输入exit。你可以在那里扔垃圾。你的关键和价值是什么。关键和价值是最重要的!如果您仍然面临问题,请告诉我。是的,我有搜索路线和索引视图,问题是列出了所有可能的事件我既看不到关键字也看不到值,我看到的唯一参数是城市:,日期:和类别:所有内部事件可能我遗漏了什么,最让我困惑的是如何处理键和值。@Bluespheal键是您要筛选的字段名,值是您为搜索输入的字段的值。e、 g.在文本字段名称中输入test并进行搜索。。然后名称变成键,值变成测试。明白了吗?哦!现在我明白了,我仍然无法过滤日期值:“2017-06-30”,城市:Tulum,类别:Cultura,但所有事件都使用@resources.each do | event |列出。我觉得我遗漏了一些明显的东西……这一个非常好,但我会坚持一段时间,直到我完全实现下面的答案,尽管如此,这一个更容易理解。@events.all.distinct.each使所有事件在有多个类别的情况下只列出一次。这一个非常好,但是我会坚持一段时间,直到完全实现下面的答案,不过,这一条更容易理解。@events.all.distinct.each使所有事件在有多个类别时只列出一次。