我正在尝试实现包含名字、姓氏、电子邮件、项目名称、功能名称的用户记录的搜索功能。
这里的名字、姓氏和电子邮件来自一个表(用户),项目名称来自表项目,特征名称来自表特征。模型关联如下所示。
我有一个用户索引页面,其中列出了用户表中的所有用户。需要搜索我们正在输入的用户。
模型用户.rb:
class User < ApplicationRecord
has_many :project_users, dependent: :destroy
has_many :projects, through: :project_users, dependent: :destroy
end
用户有名字、姓氏、电子邮件等字段(使用这三个字段进行搜索)
模型项目.rb
class Project < ApplicationRecord
belongs_to :user
has_many :project_users, dependent: :destroy
has_many :features, dependent: :destroy
has_many :users, through: :project_users, source: :user
end
项目有project_name(我们使用项目名称搜索)
模型特征.rb
class Feature < ApplicationRecord
belongs_to :project
end
Feature有feature_name(有了feature_name我们需要搜索)
我在寻找什么
我们有 params[:search_member],其中包含搜索的项目(first_name、last_name、email、project_name、feature_name
例如:
params[:search_member] = "John"
params[:search_member] = "Project1"
params[:search_member] = "Feature1"
params[:search_member] = "[email protected]"
需要一个查询来检查这三个表(用户、项目和功能)中字段first_name、last_name、email、project_name 和feature_name 中的“params[:search_member]”,并返回搜索值的用户。
协会工作
current_user.projects # will return all projects belongs to current user
project.users # return all users belongs to project
feature.project # return project that feature belongs to
和
feature.project.users # will return all users of projects
def search_all
if params[:search_member].present?
#need query here
else
User.all
end
end
如果我输入project_name,它将返回该特定项目的所有用户
如果我输入名字、姓氏或电子邮件,则会返回此详细信息的所有用户
如果我输入功能名称,则返回该功能所属项目的所有用户
尝试在单个连接查询中进行
我会尝试这个
def search_all
if params[:search_member].present?
User.includes(projects: :features)
.where(first_name: params[:search_member])
.or(User.where(last_name: params[:search_member])
.or(User.where(email: params[:search_member])
.or(Project.where(project_name: params[:search_member]))
.or(Feature.where(feature_name: params[:search_member]))
else
User.all
end
end
如果这按预期工作,那么我会将不同的子查询重构到模型中的范围,以使其更易于阅读。
我建议使用 pg_search gem (更好的质量,更干净的代码),然后它可以像这样:
class User < ApplicationRecord
has_many :project_users, dependent: :destroy
has_many :projects, through: :project_users, dependent: :destroy
has_many :features, through: :projects
pg_search_scope :search_member,
against: [:first_name, :last_name, :email],
associated_against: {
projects: :name,
features: :name
}
end
然后:
def search_all
if params[:search_member].present?
User.search_member(params[:search_member])
else
User.all
end
end
解决方案
if params[:search_member].present
search = params[:search_member]
User.joins(projects: :features).where('users.first_name ILIKE :search
OR users.last_name ILIKE :search
OR users.email ILIKE :search
OR projects.project_name ILIKE :search
OR features.name ILIKE :search', search: "%#{search}%").references(:projects).uniq
else
User.all
end