利用ransack实现搜索功能

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>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容