Step 1.安装gems
app/Gemfile
...
+ gem 'ransack'
+ gem 'will_paginate'
+ gem 'will_paginate-bootstrap'
+ gem 'seo_helper'
...
执行bundle install
重启rails s
Step 2.建立 search action
app/controllers/products_controller.rb
class ProductsController < ApplicationController
+ before_action :validate_search_key, only: [:search]
...
+ def search
+ if @query_string.present?
+ search_result = Product.ransack(@search_criteria).result(:distinct => true)
+ @products = search_result.paginate(:page => params[:page], :per_page => 5 )
+ end
+ end
+ protected
+ def validate_search_key
+ @query_string = params[:q].gsub(/\\|\'|\/|\?/, "") if params[:q].present?
+ @search_criteria = search_criteria(@query_string)
+ end
+ def search_criteria(query_string)
+ { :title_cont => query_string }
+ end
private
...
Step 3.建立 search action 的表单
touch app/views/products/search.html.erb
app/views/products/search.html.erb
<div>
<br>
<% if @query_string.blank? %>
<div class="search-info-title">
Sorry, The search content cannot be blank, pleace type some product into to search.
</div>
<% elsif @products.blank? %>
<br>
<h2 class="search-info-title"> 请输入关键字...</h2>
<% else %>
<h2 class="search-info-title">有关"<%= @query_string %>"的信息</h2>
<div class="search_result">
<div class="row groups-show0"></div>
<div class="group-table">
<% @products.each do |product| %>
<div class="row groups-show">
<div class="col-md-12 col-lg-9 col-lg-offset-1">
<div class="pull-right">
发布时间:<%= product.created_at.to_date %>
</div>
<p><%= link_to(render_highlight_content(product, @query_string),product_path(product)) %></p>
</div>
</div>
<% end %>
</div>
</div>
<div class="text-center">
<%= will_paginate(@product, renderer: BootstrapPagination::Rails) %>
</div>
<% end %>
</div>
Step 4.修改 app/views/common/_navbar.html.erb
app/views/common/_navbar.html.erb
<div class="navbar-collapse navbar-ex1-collapse collapse" aria-expanded="false">
<ul class="nav navbar-nav">
...略
</ul>
+ <ul class="nav navbar-nav navbar-left">
+ <%= form_tag search_products_path, :method => :get do %>
+ <div class="input-group" id="search-id" >
+ <input type="text" class="form-control" name="q" value="<%= params[:q] %>" placeholder="请输入搜索内容...">
+ <div class="input-group-btn">
+ <button class="btn btn-default" type="submit">
+ <i class="glyphicon glyphicon-search"></i>
+ </button>
+ </div>
+ </div>
+ <% end %>
+ </ul>
<ul class="nav navbar-nav navbar-right">
...略
</ul>
</div>
Step 5.使用自定义Helper
app/helpers/products_helper.rb
module GroupsHelper
+ def render_highlight_content(product,query_string)
+ excerpt_cont = excerpt(product.title, query_string, radius: 500)
+ highlight(excerpt_cont, query_string)
+ end
end
Step 6.让“ransack”与“products”产生关联
app/config/routes.rb
...
resources :products do
member do
post :add_to_cart
end
+ collection do
+ get :search
+ end
end
...
Step 7.修饰细节
app/assets/stylesheets/application.scss
+ .navbar-left {
+ float: initial;
+ margin-top: 10px;
+ width: 300px;
+ }
+ .search-id {
+ width: 200px;
+ padding-top: 7px;
+ }
+ .page-wrap {
+ margin-top: 50px;//搜索页面距离顶部的距离
+ }
+ .input-group {
+ left: 13px;//搜索栏距离左边距离
+ }
如何利用ransack实现搜索功能(2方案)
Step 1.安装gem ransack
ransack会用数据库的LIKE语法来做搜寻,虽然比较方便,但它会依次检查资料是否符合,而不会使用数据库的索引。如果数据比较庞大的话,利用ransack将不会是一个好的选择。这时候我们就可以安装专门的全文搜索引擎,例如Elasticsearch
Gemfile
+ gem 'ransack'
bundle
重启 rails s
Step 2.controller与config的设定
1、设置路由
config/routes.rb
Rails.application.routes.draw do
devise_for :users
resources :posts do
+ collection do #我们会搜索出所有符合关键字的文章,结果为复数,因此用collection,而不是member
+ get :search
+ end
end
end
2、 设置controller
主要设置通过哪些关键词进行搜索。
app/controllers/posts_controller.rb
class PostsController < ApplicationController
before_action :validate_search_key, only: [:search]
def search
if @query_string.present?
@posts = search_params #搜索post的关键词
end
end
protected # 放在最后
def validate_search_key
# gsub 是Ruby中正则表达式的方法,它会切换所有匹配到的部分
@query_string = params[:q].gsub(/\\|\'|\/|\?/, "")if params[:q].present?
end
def search_params
Post.ransack({:title_or_content_cont => @query_string}).result(distinct: true)
#title与content是post的两个栏位,而我们的关键词出自这里
end
end
Step 3.views的设定
1、导航栏的显示
app/views/common/_navbar.html.erb
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
+ <ul class="nav navbar-nav">
+ <li>
+ <div class="form-group form-inline search-bar">
+ <%= render :partial => "posts/search_bar"%>
+ </div>
+ </li>
+ </ul>
…… 略
</div>
执行touch app/views/posts/_search_bar.html.erb
并编辑
app/views/posts/_search_bar.html.erb
<div class="row">
<div class="col-sm-9 col-lg-8 col-lg-offset-2">
<%= form_tag search_posts_path, :class => "posts-search-form", :method => :get do %>
<div class="input-group">
<input type="text" class="form-control search-bar-input" name="q" value="<%= params[:q] %>" placeholder="关键词">
<span class="input-group-btn">
<button type="submit" class="btn btn-default search-bar-submit">
<span class="glyphicon glyphicon-search"></span>
</button>
</span>
</div>
<% end %>
</div>
</div>
2.搜索反馈页面
新增 app/views/posts/search.html.erb
app/views/posts/search.html.erb
<div class="minHeight1000 bg-gray">
<div class="search-page w1200 pt30 bc">
<% if @posts.present? %>
<h5 class="collection search-count">已为您找到<%= @posts.count %>篇相关文章</h5>
<% else %>
<p class="tc mt100">未搜索到任何文章,要不换个关键词试试?</p>
<% end %>
</div>
<div class="container">
<% @posts.each do |post| %>
<div class="panel panel-default">
<div class="panel-body">
<%= post.title %>
<br/>
<br/>
<span id="psot-thumbsup-<%= post.id%>" class=" label label-success"><%= post.likes.count%>👍</span>
<div class="text-right">
<% if !current_user.is_collect_of?(post) %>
<%= link_to("收藏", collect_post_path(post), method: :post, class: "btn btn-sm") %>
<% else %>
<%= link_to("取消收藏", uncollect_post_path(post), method: :post, class: "btn btn-sm") %>
<% end %>
</div>
</div>
</div>
<% end %>
</div>
</div>