利用ransack做搜索功能

本篇教程基于自己的一个小项目,用户可以搜索网站上其他用户发表过的文章。

第一歩:

安装gem ransack

ransack会用数据库的LIKE语法来做搜寻,虽然比较方便,但它会依次检查资料是否符合,而不会使用数据库的索引。如果数据比较庞大的话,利用ransack将不会是一个好的选择。这时候我们就可以安装专门的全文搜索引擎,例如Elasticsearch

Gemfile
1
+  gem 'ransack'

$ bundle,重启 rails s

第二歩

controller与config的设定

1、设置路由

config/routes.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
  Rails.application.routes.draw do
devise_for :users
resources :posts do
+ collection do #我们会搜索出所有符合关键字的文章,结果为复数,因此用collection,而不是member
+ get :search
+ end
end
end
```

#### 2、设置controller
主要设置通过哪些关键词进行搜索。
```ruby 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

第三歩

views的设定

1、导航栏的显示

app/views/common/_navbar.html.erb
1
2
3
4
5
6
7
8
9
10
 <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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
 <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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<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>

效果图