Ruby on Rails中如何通过关键词搜索关联表的用户信息?
Rails证书搜索功能修复方案
问题背景
模型关系:
Certificate关联Program(belongs_to :program)Certificate关联User(belongs_to :user)
视图中已实现搜索表单,通过keyword参数搜索用户的姓名(name)和邮箱(email):
<%= form_tag admin_program_path(@program), :method => :get do %> <%= text_field_tag :keyword, params[:keyword], :placeholder => "Search by name or email", :class => "form-control rounded" %> <%= submit_tag "Search", :class => "btn btn-outline-secondary" %> <% end %>
用户编写的控制器代码无法正常工作:
@certificates = @program.certificates.includes(:user).order("id DESC") if params[:keyword].present? keyword = "%#{params[:keyword].strip}%" @certificates = @certificates.user.where('name LIKE ? OR email LIKE ?', keyword, keyword) end
问题原因
@certificates是证书集合对象,不能直接调用.user方法(该方法仅适用于单个Certificate实例),导致查询语法错误。
修复代码
方案一:JOIN关联用户表查询
@certificates = @program.certificates.includes(:user).order(id: :desc) if params[:keyword].present? keyword = "%#{params[:keyword].strip}%" @certificates = @certificates.joins(:user).where('users.name LIKE ? OR users.email LIKE ?', keyword, keyword) end
- 用
joins(:user)关联用户表,查询时需指定表名users.避免字段冲突 order(id: :desc)是Rails规范写法,替代字符串形式的排序语句
方案二:Rails 5+ 安全关联查询语法
@certificates = @program.certificates.includes(:user).order(id: :desc) if params[:keyword].present? keyword = "%#{params[:keyword].strip}%" name_condition = @certificates.where(users: { name: keyword }) email_condition = @certificates.where(users: { email: keyword }) @certificates = name_condition.or(email_condition) end
- 无需手动编写SQL片段,Rails自动处理表名与参数绑定,降低SQL注入风险
补充提示
includes(:user)用于预加载用户数据,避免N+1查询问题- 若需大小写不敏感搜索:PostgreSQL替换
LIKE为ILIKE;MySQL可设置表字符集为utf8mb4_general_ci(默认不区分大小写)
内容的提问来源于stack exchange,提问作者Chaos TW
相关产品推荐
相关产品推荐

