常見的情境有,搜索用戶資料、搜尋文章等等
而在 Rails 裡面有一個做基礎搜尋功能的 gem 他叫 Ransack,之所以會說只能做基本搜尋是因為,他是在下搜尋關鍵字的時候,從 database 裡面做模糊搜索,使用 like 去做 query
例如我們要搜尋 User 的 first name,名叫 Nic 的資料
在 ransack 裡面的寫法是
User.ransack(first_name_cont: 'Nic')
而他轉成 SQL 就會變成
SELECT "users".* FROM "users" WHERE ("users"."first_name" LIKE '%Nic%')
除了「模糊搜索」以外,需要更精準的搜索就需要用到「全文搜索」了
這部份就可以參考全文搜索的引擎(需要額外架設)
- solr
- elasticsearch
不過這篇就只說使用 ransack 在 Rails App 裡面實作搜尋吧
設計目標
- 單獨的 Search Controller
- 漂亮的路徑
example.com/search?#{search_key_word}
安裝 ransack
gem 'ransack'
設定 controller 與 routes
創建 search controller
rails g controller search
get "/search" => "search#index", :as => "search"
接下來我們要處理透過 form 送進來的 params,濾掉一些不必要的字符,這部份可以在 controller 裡面做 validation
def validate_search_key
@query_string = params[:q].gsub(/\\|\'|\/|\?/, "") if params[:q].present?
@search_criteria = search_criteria(@query_string)
end
然後告訴 controller 我們要搜尋的範圍
def search_criteria(query_string)
{ :title_or_description_cont => query_string }
end
title_or_description_cont
是ransack提供的方法 意思是說,搜尋這個 model 裡面的 title 或是 description 欄位
接下來我們完成 index action
def index
if @query_string.present?
@search = Topic.search(@search_criteria).result(:distinct => true)
end
end
接下來只要將其搜尋結果,用 view 呈現出來,搜尋功能就完成了。
在這邊我們看到的 web url 會是
http://example.com/search?utf8=✓&q=test
其中的 q=test
就是我們從 form 送進去的搜尋內容
utf8=✓
則是為了符合古老的瀏覽器 ie6
, Rails 在 form 裡面幫我們自帶的 attribute
附上最後拼湊完成的 Search Controller
class SearchController < ApplicationController
before_action :validate_search_key
def index
if @query_string.present?
@search = Topic.search(@search_criteria).result(:distinct => true)
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_content_cont => query_string }
end
end