You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails 5简易搜索表单无法正常工作,请求技术支持

实现全站共享导航栏的Post标题搜索功能

没问题,我来帮你把这个搜索功能完整落地,咱们一步步来:

1. 确保导航栏表单正确渲染到全局布局

你已经有了表单代码,只需要把它放到application.html.erb的导航栏区域里(比如Bootstrap的navbar内部),这样所有视图都会共享这个搜索框:

<!-- 在application.html.erb的导航栏合适位置插入 -->
<form class="form-inline d-none d-lg-inline-flex">
  <%= form_tag search_query_path, method: :get do %>
    <%= text_field_tag :query, params[:query], class: "form-control mr-2", placeholder: "搜索文章标题..." %>
    <%= submit_tag "搜索", class: "btn btn-primary", name: nil %>
  <% end %>
</form>

我给表单元素加了点Bootstrap的间距类,让样式更美观,你可以根据自己的样式需求调整。

2. 在Post模型中添加标题搜索逻辑

在app/models/post.rb里定义一个scope(或者类方法),用来匹配包含搜索关键词的标题:

class Post < ApplicationRecord
  # 用scope实现模糊搜索,支持部分匹配
  scope :by_title, ->(query) { where("title LIKE ?", "%#{query}%") if query.present? }

  # 也可以用类方法实现,逻辑完全一致
  # def self.by_title(query)
  #   return all unless query.present?
  #   where("title LIKE ?", "%#{query}%")
  # end
end

这里用LIKE做模糊匹配,如果你的数据库是PostgreSQL,也可以换成ILIKE实现大小写不敏感搜索;如果后续需要更精准的全文搜索,再考虑pg_search这类gem就行,目前这个简单实现足够满足基础需求。

3. 在PostsController中实现搜索动作

在app/controllers/posts_controller.rb里添加search_query方法,处理搜索请求并返回结果:

class PostsController < ApplicationController
  # 处理搜索请求
  def search_query
    @query = params[:query]&.strip
    # 调用模型的搜索方法获取匹配结果,按创建时间倒序排列
    @posts = Post.by_title(@query).order(created_at: :desc)

    # 两种渲染选择:复用index页面模板,或者用专门的搜索结果页面
    # 如果有单独的搜索结果视图,就写render :search;这里默认复用index模板
    render :index
  end
end

如果需要专门的搜索结果页面,你可以创建app/views/posts/search.html.erb来定制展示样式。

4. 配置路由

最后要在config/routes.rb里添加对应的路由,让search_query_path能正确指向控制器动作:

Rails.application.routes.draw do
  # 其他已存在的路由...
  get 'search_query', to: 'posts#search_query', as: 'search_query'
end

这样表单提交的请求就会正确路由到PostsController的search_query方法了。

测试一下:在导航栏输入关键词点击搜索,就能看到匹配标题的Post列表啦!

内容的提问来源于stack exchange,提问作者Hiago Serpa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:53:37