如何使用ransake来加一个job搜索功能?

Published on:

写在前面:

感谢这篇文章: 使用ransake写搜索功能——fullstack-course 第四周/最棒的概念或工具 « linzhewei’s Blog
本篇文章是根据这篇文章改写的,根据我自己的情况来总结的文字,可能会出现bug。


1. 安装需要的gem

Gemfile
gem 'ransack'
gem 'will_paginate-bootstrap'
gem 'seo_helper'

一般来说,我们需要will_paginate来增加分页功能,让页面更加简洁好看。

2. 在相应的页面加入一个搜索框,供user搜索

比如我要在job-list page 上方加一个搜索框,那就在views/jobs/index.html.erb,这个文档的开头写上如下代码:

app/views/jobs/index.html.erb
<%= render :partial => “jobs/search_bar” %>

然后新建一个search_bar:
$ touch app/views/jobs/_search_bar.html.erb

写入酱紫的代码:(”#”路径,后面会更改)

_search_bar.html.erb
<div class=“row”>
  <div class=“col-sm-9 col-lg-8 col-lg-offset-2>
    <%= form_tag “#” ,:method => :get, :class => “jobs-search-form” do %>
      <div class=“input-group”>
        <input type=“text” class=“form-control” name=“q” value=“<%= params[:q] %>” placeholder=“search for keyword…”>

        <span class=“input-group-btn”>
          <button type=“submit” class=“btn btn-default btn-info>
            <span class=“glyphicon glyphicon-search></span>
          </button>
        </span>
      </div>
    <% end %>
  </div>
</div>

3. 完善controller

修改jobs_controller.rb,加入如下代码:

jobs_controller.rb
before_action :validate_search_key, only: [:search]

def search
    if @query_string.present?
      search_result = Job.published.ransack(@search_criteria).result(:distinct => true)
      @jobs = search_result.paginate(:page => params[:page], :per_page => 20 )
    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_description_cont => query_string } #搜索匹配title和description,可以加其他关键词匹配

  end

4. 完善routes

修改routes.rb:

routes.rb
 resources :jobs do
    collection do
      get :search
    end
  end

注意:
如果报错no defined routes jobs/search,可以考虑把get :search改成

routes.rb
match 'search' => 'jobs#search', via: [:get, :post], as: :search

5. 新增搜索页面

新建文档:
$ touch app/views/jobs/search.html.erb

加入如下代码:

search.html.erb
 <%= render :partial => "jobs/search_bar" %>

  <div class="col-md-12">

    <% if @jobs.blank?%>
      <br>
      <h3 class="text-center">
        Opps! No jobs matched yet, please try again.
      </h3>
    <% else %>
      <h3 class="text-center" style="margin-top: 30px;">Total find <%= @jobs.count %> jobs</h3>
      <hr />
       <%= render :partial => "jobs_item", :collection => @jobs, :as => :job %>
      <div class="text-center">
        <%= will_paginate @jobs, renderer: BootstrapPagination::Rails %>
      </div>
    <% end %>
  </div>
_jobs_item.html.erb
<table class="table table-boldered">
  <thead>
    <tr>
      <td>Job Supply</td>
      <td>Wage Lower Bound</td>
      <td>Wage Upper Bound</td>
      <td>Post Time</td>
    </tr>
  </thead>
  <tbody>
    <% @jobs.each do |job|%>
      <tr>
        <td>
          <%= link_to(render_highlight_content(job,@query_string),job_path(job))%>
        </td>
        <td><%= job.wage_lower_bound%></td>
        <td><%= job.wage_upper_bound%></td>
        <td><%= local_time(job.created_at, '%B %e, %Y %l:%M%p')%></td>
      </tr>
    <% end %>
  </tbody>
</table>

6. 修改_search_bar里的路径

更改”#" 路径:

_search_bar.html.erb
<%= form_tag search_jobs_path , :class => "jobs-search-form" do %>

7. 制作搜索的highlight功能

app/helpers/jobs_helper.rb里添加如下代码:

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

这样,我们就可以修改app/views/jobs/search.html.erb里的代码:
<%= link_to(job.title,job_path(job)) %>改成:
<%= link_to(render_highlight_content(job,@query_string),job_path(job)) %>

如此一来,我们就能实现搜索功能了,如果是购物网站,把jobs一键替换成products就行。

Comments

comments powered by Disqus