搜索多个字段 rails 5
Posted
技术标签:
【中文标题】搜索多个字段 rails 5【英文标题】:Search multiple fields rails 5 【发布时间】:2021-07-13 17:52:27 【问题描述】:我有以下表格:
<div class='panel' id='panel-advanced-search'>
<%= form_tag contacts_path, method: :get do %>
<div>
<div class='advanced_search'>
<div>
<%= label_tag "Contact Type" %>
<%= select_tag(:contact_type, options_for_select(Contact::TYPES, selected: params[:contact_type]), prompt: 'Any', class: 'customSelect') %>
</div>
<div>
<%= label_tag "Prospect Strength" %>
<%= select_tag(:prospect_strength, options_for_select(Contact::PROSPECT_STRENGTHS, selected: params[:prospect_strength]), prompt: 'Any', class: 'customSelect') %>
</div>
<div>
<%= label_tag "Customer" %>
<%= collection_select(:customer_account_id, :customer_account_id, Customer.order(:name), :id, :name, prompt: '' , class: 'customSelect select2') %>
</div>
<div>
<%= label_tag "Supplier" %>
<%= collection_select(:supplier_account_id, :supplier_account_id, Supplier.order(:name), :id, :name, prompt: '' , class: 'customSelect select2') %>
</div>
<div>
<%= label_tag "Company Name" %>
<%= text_field_tag :company_name %>
</div>
<div>
<%= label_tag "Name" %>
<%= text_field_tag :name %>
</div>
<div>
<%= label_tag "Job Title" %>
<%= text_field_tag :title %>
</div>
<div>
<%= label_tag "Postcode" %>
<%= text_field_tag :postcode %>
</div>
<div>
<%= label_tag :created_at, 'Created From' %>
<div class="date-picker">
<%= text_field_tag :created_at, nil, class: 'date-picker-select' %>
<span class="date-picker-btn">
<span class="icon-calendar" aria-hidden="true"></span>
</span>
</div>
</div>
<div>
<%= label_tag :updated_at, 'Created To' %>
<div class="date-picker">
<%= text_field_tag :updated_at, nil, class: 'date-picker-select' %>
<span class="date-picker-btn">
<span class="icon-calendar" aria-hidden="true"></span>
</span>
</div>
</div>
<div>
<%= label_tag "Tags" %>
<%= collection_select(:tag_list, :tag_list, @tags.order(:name), :name, :name, , class: 'select2', multiple: true ) %>
</div>
<div>
<%= label_tag "Assignee" %>
<%= collection_select(:assigned_to, :assigned_to, User.all, :id, :name, prompt: 'Any' , class: 'customSelect select2') %>
</div>
<div>
<%= label_tag "Obsolete?" %>
<%= select_tag(:obsolete, options_for_select(['Obsolete', 'All'], selected: params[:obsolete]), prompt: 'Not obsolete?', class: 'customSelect') %>
</div>
<div>
<%= label_tag "Send Results To" %>
<%= select_tag(:subsequent_action, options_for_select([
['Report', 'report'],
['CSV Export', 'csv_export'],
['New Event', 'new_event']
]), prompt: 'None', class: 'customSelect') %>
</div>
</div>
<div class="advanced_search_btns">
<%= submit_tag submit_text %>
<%= link_to secondary_btn, contacts_path, class: 'btn-medium' %>
</div>
</div>
<% end %>
</div>
以及模型中的以下方法
def self.advanced_search
Contact.where('
contact_type LIKE :search OR
prospect_strength LIKE :search OR
customer_account_id LIKE :search OR
supplier_account_id LIKE :search OR
company_name LIKE :search OR
name LIKE :search OR
title LIKE :search OR
postcode LIKE :search OR
created_at LIKE :search OR
updated_at LIKE :search OR
tag_list LIKE :search OR
assigned_to LIKE :search OR
obsolete LIKE :search
', search: "%#search%"
)
end
我该如何使用这种方法,以便用户可以使用这个带有多个参数的搜索表单?我已经在 index 方法中有以下基本搜索,所以我需要有两个搜索表单
def index
@per_page = params[:per_page] || 20
@tags = ActsAsTaggableOn::Tag.all
if params[:search].present?
@contacts = Contact.search(params[:qs], params[:search]).order(sort_column + ' ' + sort_direction).paginate(page: params[:page], per_page: @per_page)
else
@contacts = Contact.all.order(sort_column + ' ' + sort_direction).paginate(page: params[:page], per_page: @per_page)
end
end
编辑将上面的表单更新为完整的表单,理想情况下,我希望表单功能完全在模型中。
编辑#2
这是基本搜索:
型号
QUICK_SEARCH_FIELDS =
name:
column_names: 'contacts.name'
,
customers:
joins_table: :customer,
column_names: 'contacts.name',
filters: contact_type: 'customer'
,
suppliers:
joins_table: :supplier,
column_names: 'contacts.name',
filters: contact_type: 'supplier'
,
tags:
tagged_with: true
.with_indifferent_access
def self.search(field, query)
field = QUICK_SEARCH_FIELDS[field]
contact = all
contact = contact.joins(field[:joins_table]) if field[:joins_table]
contact = contact.where(field[:filters]) if field[:filters]
contact = contact.where("#field[:column_names] LIKE ?", "%#query%") if field[:column_names]
contact = contact.tagged_with(query) if field[:tagged_with]
contact
end
表格
<div class='panel' id='panel-search'>
<%= form_tag contacts_path, method: :get do %>
<div class='l-inline-row-block'>
<div class='l-inline-col width_120px'>
<%= select_tag(:qs, options_for_select(Contact::QUICK_SEARCH_FIELDS.keys(), selected: params[:qs]), class: 'customSelect') %>
</div>
<div class='l-inline-col'>
<%= search_field_tag :search, params[:search] %>
</div>
<div class='l-inline-col' style='width: 100px;'>
<%= submit_tag submit_text %>
</div>
</div>
<% end %>
</div>
【问题讨论】:
在高级搜索中:用户可以从多个字段中选择一个值进行搜索,但他也可以保持该字段为空例如:用户想要搜索contact_type
中的内容但不是在prospect_strength
?字段之间的搜索词也可以不同吗?
是的,是的,是的,字段之间的搜索词可能不同,但如果用户想要搜索 contact_type
和 prospect_strength
,他们应该能够以及他们的任何其他字段想要添加到搜索中。
我知道您需要简单的表单和高级搜索:但不能同时使用,对吗?还是他们?哪一个先例?如果有高级搜索,是否也使用普通搜索?
不是同时不,这取决于用户他们想在那里使用哪一个完全分开。明智的选项卡首先是基本搜索选项卡,因此这是用户首先看到的内容,但两者之间没有字段共享或任何内容。两个搜索同时在页面上,但完全不同的形式。
【参考方案1】:
您可能需要进行视图调整,并且不能只对所有字段使用 search
术语/查询:
1.确保视图中表单内的字段与联系人模型中需要搜索的列的名称相同 2.在每个表单中添加一个隐藏字段,以便您确定这是哪个搜索(还有另一种选择,但这个工作较少) 3.将用户只能选择一个字段的collection_select更改为select_tag,以免弄乱查询构建
每个填充的字段都会传递一个值 - 您可以构建一个哈希值,包括输入的列/表单字段及其值,例如 contact_type: "value1", prospect_strength: "value2"
之后,您需要使用该哈希构建查询并查询数据库
看起来像这样:
在你看来:
将此添加到高级搜索表单中
<%= hidden_field_tag :search_type, :advanced %>
然后在您的正常搜索中添加这个
<%= hidden_field_tag :search_type, :normal %>
在您的模型中:
def self.advanced_search(values_by_column_name) # values_by_column_name is a hash passed from the controller
tag_list = values_by_column_name.delete("tag_list")
sql_query = values_by_column_name.keys.map |column| "#column LIKE :#column"
sql_query = sql_query.join(" OR ")
values_by_column_name = values_by_column_name.transform_values |value| "%#value%" .symbolize_keys
relation = Contact.where(sql_query, values_by_column_name)
relation = relation.tagged_with(tag_list) if tag_list
relation
end
在您的控制器中:
ADVANCED_SEARCH_FIELDS = [
:contact_type,
:prospect_strength,
:customer_account_id,
:supplier_account_id,
:company_name,
:name,
:title,
:postcode,
:created_at,
:updated_at,
tag_list: [],
:assigned_to,
:obsolete,
]
def index
@per_page = params[:per_page] || 20
@tags = ActsAsTaggableOn::Tag.all
if advanced_search?
@contacts = Contact.advanced_search(advanced_search_params)
elsif normal_search?
@contacts = Contact.search(params[:qs], params[:search])
else
@contacts = Contact.all
end
@contacts = @contacts.order(sort_column + ' ' + sort_direction).paginate(page: params[:page], per_page: @per_page)
end
def advanced_search?
params[:search_type] == "advanced" && advanced_search_params.any?
end
def normal_search?
params[:search_type] == "normal" && params[:search].present?
end
def advanced_search_params
@_advanced_search_params ||= params.permit(ADVANCED_SEARCH_FIELDS).select |_, v| v.present? .to_h
end
【讨论】:
是否可以将高级搜索字段移动到模型中,因为这是一个理想情况下应该属于模型的数据库查询?还有不同的字段类型不仅仅是选择字段,所以还有文本和选择字段 什么意思?现在高级搜索字段在哪里?联系人数据库中不是所有这些字段吗? 让我用整个表格更新问题,所有这些字段都在联系人表中是的。高级搜索不应该有任何默认值,它应该是空白的,所以我们不应该默认为contact_type
更新问题
我知道你能在这里评论一下:高级搜索的参数和普通搜索的参数?我想看看区别,是否有任何特殊键可以帮助确定区别以上是关于搜索多个字段 rails 5的主要内容,如果未能解决你的问题,请参考以下文章