Rails结合will_paginate实现支持全库检索的分页用户搜索功能求教
实现方案
1. 调整后端控制器逻辑
将原来先分页再搜索的逻辑改成先全量匹配搜索条件,再执行分页,所有数据过滤操作在数据库层面完成:
# 取出搜索关键词,去除前后空格 search_key = params[:search].to_s.strip # 初始化用户查询对象 @user_list = User.all # 存在搜索关键词时追加匹配条件,示例匹配姓名、邮箱两个字段,可按需扩展 if search_key.present? # PostgreSQL用ILIKE实现不区分大小写匹配,MySQL请替换为LIKE @user_list = @user_list.where("name ILIKE ? OR email ILIKE ?", "%#{search_key}%", "%#{search_key}%") end # 过滤完成后再执行分页 @user_list = @user_list.paginate(page: params[:page], per_page: 100)
注意:这里使用ActiveRecord参数绑定语法传入搜索值,可避免SQL注入风险,不要直接拼接SQL字符串。
2. 修改视图代码
需要调整搜索框逻辑,同时让分页组件携带搜索参数,避免分页时丢失搜索条件:
<!-- 搜索表单用GET提交,参数保留在URL中方便分页、分享 --> <div class="col-md-4" style="float: left;"> <%= form_tag '', method: :get do %> <%= text_field_tag :search, params[:search], class: "form-control", title: "Search", placeholder: "搜索 🔍 :" %> <% end %> </div> <br><br> <!-- 分页组件追加search参数,点击下一页时会携带当前搜索关键词 --> <%= will_paginate @user_list, params: { search: params[:search] } %> <table id="users_access_table"> <thead> <tr> <th>Name</th> <th>Email</th> <th>Current Access</th> <th>API User Access</th> </tr> </thead> <tbody id="table_body"> <% @user_list.each do |user| %> <tr> <td><%= user.name %></td> <td><%= user.email %></td> <td><%= user.access %></td> <td><%= user.api_users %></td> </tr> <% end %> </tbody> </table>
做完以上两步就可以实现全量数据搜索+分页的基础功能,原有仅作用于当前页的前端jQuery过滤逻辑可以直接删除。
(可选)实现无刷新AJAX搜索
如果需要避免页面刷新,提升使用体验,可以参考以下JS代码替换原有searchUsers逻辑:
let searchTimer = null // 页面加载完成后绑定事件 document.addEventListener('DOMContentLoaded', () => { bindPaginationClick() // 输入框输入延迟300ms触发搜索,避免请求过于频繁 document.getElementById('userinput').addEventListener('keyup', () => { clearTimeout(searchTimer) searchTimer = setTimeout(searchUsers, 300) }) }) // 搜索请求逻辑 function searchUsers() { const searchVal = document.getElementById('userinput').value const requestUrl = new URL(window.location.pathname, window.location.origin) requestUrl.searchParams.set('search', searchVal) fetch(requestUrl, { headers: { 'Accept': 'text/html' } }) .then(res => res.text()) .then(html => updatePageContent(html)) } // 分页链接点击事件绑定,实现无刷新分页 function bindPaginationClick() { document.querySelectorAll('.pagination a').forEach(link => { link.addEventListener('click', e => { e.preventDefault() const pageUrl = new URL(link.href) pageUrl.searchParams.set('search', document.getElementById('userinput').value) fetch(pageUrl, { headers: { 'Accept': 'text/html' } }) .then(res => res.text()) .then(html => updatePageContent(html)) }) }) } // 替换页面表格和分页内容 function updatePageContent(html) { const tempDom = new DOMParser().parseFromString(html, 'text/html') document.getElementById('table_body').innerHTML = tempDom.getElementById('table_body').innerHTML document.querySelector('.pagination').innerHTML = tempDom.querySelector('.pagination').innerHTML bindPaginationClick() }
性能优化建议
如果用户数据量超过10万,建议给name、email等参与搜索的字段添加数据库索引,大幅提升搜索查询速度。
内容的提问来源于stack exchange,提问作者User1984
相关产品推荐
相关产品推荐

