about 1 year ago

搜索功能,目前主要有两种方式:

  1. 做在navbar上

  2. 做在Products#index,或者Product#show 页面内




方案1:navbar实现搜索功能

Step1.安装gem

在Gemfile中加入如下gem:
gem ‘ransack’
gem ‘will_paginate’
gem 'will_paginate-bootstrap'
gem ‘seo_helper’

备注:
gem 'will_paginate-bootstrap'用来美化分页效果的。
gem ‘seo_helper’用于高亮显示搜索结果
执行:bundle install

执行完毕后,重新开启rails server。

Step2.在_navbar.html.erb中的某个位置添加代码如下代码:

app/views/common/_navbar.html.erb
<div class="nav navbar-nav navbar-left">
  <%= form_tag "#" , :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 %>
</div>

备注:CSS格式可以自己调节。

Step3.在products_controller.rb中添加相关功能方法

app/controllers/products_controller.rb
略...

 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_or_description_cont: query_string }
   end

备注:title_or_description_cont,表示搜索内容限于product的title和description,也可以加入product的其他栏位。

Step4.修改routing,加入search

config/routes.rb
  resources :products do
 +   collection do
 +     get :search
 +   end
  end

执行:rake routes

Step5: 新建搜索结果显示页面

touch app/views/products/search.html.erb

app/views/products/search.html.erb
<div class="product-box">
  <div class="container">
    <!--=== 搜索结果,没有符合条件的数据 ===-->
    <% if @query_string.blank? %>
      <h2 class="search-info-title">搜索信息不能为空,请输入关键字搜索</h2>
    <% elsif @products.blank?%>
      <br>
        <h2 class="search-info-title">亲,没有搜索到商品哦,要不换个关键词试试?</h2>
    <% else %>
    <!--=== 搜索结果,有符合条件的数据 ===-->
    <!--=== 搜索內容 ===-->
    <div class='row'>
       <% @products.each do |product| %>
         <div class='col-xs-12 col-sm-4 col-md-3 product-content'>
           <%= link_to product_path(product) do %>
           <!-- 商品圖片 -->
             <% if product.image.present? %>
             <!-- 顯示圖片 -->
               <%= image_tag(product.image.thumb.url, class: "thumbnail img-responsive") %>
             <% else %>
                <%= image_tag("http://placehold.it/400x400&text=No Pic", class: "thumbnail") %>
             <% end %>
           <% end %>
           <div class="product-info">
            <p><%= link_to(render_highlight_content(product,@query_string), product_path(product)) %></p>
            <p>$ <%= product.price %></p>
           </div>
         </div>
         <% end %>
       </div>
       <div class="page-box">
         <%= will_paginate @products, renderer: BootstrapPagination::Rails, :previous_label => t('previous-label'), :next_label => t('next-label') %>
       </div>
    <% end %>
  </div>
</div>

备注:里面的search-info-title等css要自己去定义。


Step 6: 修改Step2 中 navbar内容,添加search路径

app/views/common/_navbar.html.erb
-   <%= form_tag "#" , :method => :get do %>
+   <%= form_tag search_products_path , :method => :get do %>


Step 7: 实现搜索highlight功能

在 app/helpers/products_helper.rb里添加如下代码

app/helpers/products_helper.rb
def render_highlight_content(product,query_string)
    excerpt_cont = excerpt(product.title, query_string, radius: 500)
    highlight(excerpt_cont, query_string)
end

接着把 app/views/products/search.html.erb中的如下代码做修改:

app/views/products/search.html.erb
-   <%= link_to(product.title, product_path(product)) %>
+   <%= link_to(render_highlight_content(product,@query_string), product_path(product)) %>




方案2:Products#index 或 Product#show 页面内实现搜索

Step1.安装gem

在Gemfile中加入如下gem:
gem ‘ransack’
gem ‘will_paginate’
gem 'will_paginate-bootstrap'
gem ‘seo_helper’

备注:
gem 'will_paginate-bootstrap'用来美化分页效果的。
gem ‘seo_helper’用于高亮显示搜索结果
执行:bundle install

执行完毕后,重新开启rails server。

Step2.修改 views/products/index.html.erb,在适当的位置,加入如下代码

app/views/products/index.html.erb
略
<%= render :partial => "products/search_bar" %>
略

备注:此行代码也可加入到views/products/show.html.erb,根据自己的需求。

Step3. 新建一个search_bar

touch app/views/products/_search_bar.html.erb,加入如下代码

app/views/products/_search_bar.html.erb
<div class="row">
    <div class="col-sm-9 col-lg-8 col-lg-offset-2">
        <%= form_tag "#" , :method => :get do %>
            <div class="input-group">
                <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 %>
    </div>
</div>


Step4. 在products_controller.rb中添加相关功能方法

app/controllers/products_controller.rb
略...

 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_or_description_cont: query_string }
   end

备注:title_or_description_cont,表示搜索内容限于product的title和description,也可以加入product的其他栏位。

Step5.修改routing,加入search

config/routes.rb
  resources :products do
 +   collection do
 +     get :search
 +   end
  end

执行:rake routes

Step6: 新建搜索结果显示页面

touch app/views/products/search.html.erb

app/views/products/search.html.erb
<div class="product-box">
  <div class="container">
    <!--=== 搜索结果,没有符合条件的数据 ===-->
    <% if @query_string.blank? %>
      <h2 class="search-info-title">搜索信息不能为空,请输入关键字搜索</h2>
    <% elsif @products.blank?%>
      <br>
        <h2 class="search-info-title">亲,没有搜索到商品哦,要不换个关键词试试?</h2>
    <% else %>
    <!--=== 搜索结果,有符合条件的数据 ===-->
    <!--=== 搜索內容 ===-->
    <div class='row'>
       <% @products.each do |product| %>
         <div class='col-xs-12 col-sm-4 col-md-3 product-content'>
           <%= link_to product_path(product) do %>
           <!-- 商品圖片 -->
             <% if product.image.present? %>
             <!-- 顯示圖片 -->
               <%= image_tag(product.image.thumb.url, class: "thumbnail img-responsive") %>
             <% else %>
                <%= image_tag("http://placehold.it/400x400&text=No Pic", class: "thumbnail") %>
             <% end %>
           <% end %>
           <div class="product-info">
            <p><%= link_to(render_highlight_content(product,@query_string), product_path(product)) %></p>
            <p>$ <%= product.price %></p>
           </div>
         </div>
         <% end %>
       </div>
       <div class="page-box">
         <%= will_paginate @products, renderer: BootstrapPagination::Rails, :previous_label => t('previous-label'), :next_label => t('next-label') %>
       </div>
    <% end %>
  </div>
</div>

备注:里面的search-info-title等css要自己去定义。

Step 7: 修改Step3 中的代码,添加search路径

app/views/products/_search_bar.html.erb
-   <%= form_tag "#" , :method => :get do %>
+   <%= form_tag search_products_path , :method => :get do %>


Step 8: 实现搜索highlight功能

在 app/helpers/products_helper.rb里添加如下代码

app/helpers/products_helper.rb
def render_highlight_content(product,query_string)
    excerpt_cont = excerpt(product.title, query_string, radius: 500)
    highlight(excerpt_cont, query_string)
end

接着把 app/views/products/search.html.erb中的如下代码做修改:

app/views/products/search.html.erb
-   <%= link_to(product.title, product_path(product)) %>
+   <%= link_to(render_highlight_content(product,@query_string), product_path(product)) %>




你好,如果觉得这篇文章对你有帮助,我最近在参加一个编程比赛,JD-Store 魔改大赛,喜欢的话还麻烦你投下宝贵的一票,谢谢。


参考:
http://linzhewei-blog.logdown.com/posts/796801
https://forum.qzy.camp/t/navbar/486

← ORID-W21-20170601 JDStore魔改-对Rails101进行迁移,实现product收藏功能-20170604 →
 
comments powered by Disqus