Rails 簡易搜尋功能
如果有長期關注的朋友,會覺得我怎麼現在改寫網站設計和網站工程的內容了。不要懷疑,我目前都在玩Ruby on Rails,所以也會寫相關文章,請大家多多指教。
今日分享功能:從資料庫中搜尋所有含特定字串的項目
Ruby版本:2.1.2
Rails版本:4.1.0
系統:MAC OSX 10.9.4
今天要分享的是一個Rails非常簡單的搜尋功能,比我想像中的簡單了大概一百倍。可能我原本以為要搞到像Google那樣才算是搜尋,但其實可以弄得很簡單。Railcast裡面也有非常詳盡的說明。
前提
安裝Ruby、Rails環境
已建立一個Rails程式,帶有app/views/index.html.erb頁面
有一個model叫做Product,帶有title、description (資料庫中已有數筆資料)
有一個controller包含了index action
搜尋的唯一重點就在於從view回傳一個變數 :search 回controller,剩下的就都交給Rails自建的ActiveRecord指令就好。
1. 建立搜尋表格
首先,到view當中建立一個 form_tag ,直接開始建立搜尋欄位
<%= form_tag products_path, method: :get do %>
<%= text_field_tag :search, params[:search], placeholder: "Search..." %>
<% end %>
在畫面中,就會出現一個搜尋框,簡單說明一下:
form_tag 使用的 method 方法不一,這邊要限定為method: :get,才能確實抓資料。
連結部分設定回index頁面,也可以設定為其他自訂的搜尋頁
params[:search]的使用,會回傳一個search的變數,也就是網址列的後方會出現?utf8=✓&search=search的字樣
placeholder是搜尋框內的預設文字,只要使用者輸入任何文字,這段預設文字就會消失
如果你比較喜歡要有『搜尋』這個按鈕,那可以設定為下方的樣式:
<%= form_tag admin_products_path, method: :get do %>
<%= text_field_tag :search, params[:search], placeholder: "Enter Text..." %>
<%= submit_tag "Search", name: nil %>
<% end %>
唯一有一點需要解釋的是search這顆按鈕按下去以後會預設傳送出commit=search變數到網址列裡頭,沒有意義,所以多設定了 name: nil的部份,讓他不會傳送任何其他多餘的資訊出去。
2. 建立搜尋功能
主頁面設定好以後,接下來到controller裡面進行調整:
class ProductsController < ApplicationController
def index
if params[:search]
@product = Product.where('title LIKE ?', "%#{params[:search]}%")
else
@product = Product.all
end
end
end
這個地方分成兩個區塊,邏輯是:『如果有搜尋,就把搜尋結果列出來;如果沒有進行搜尋,就把所有產品都列出來。』
where就是Rails內建用來比對資料使用
'title LIKE ?'代表product底下的title欄位是否帶有特定字串
"%#{params[:search]}%"代表我們將剛剛在view中送出的params[:search]變數傳送到這裡來進行搜尋。#{}符號是將變數正確使用於""符號內,而前後兩個%%符號代表要進行模糊比對而非精確比對,如果是直接填入params[:search]就會進行精確比對。
這樣就可以在搜尋時,讓結果頁面列出所有標題包含特定字串的model項目。到這邊就算是設定完成囉,舉國歡騰!
3. 進行多個欄位搜尋
這邊開始是RailsCast沒有講的部分,同樣分享給大家。
剛剛設定的搜尋功能,僅限於搜尋一個欄位,也就是如果要搜尋產品,就只能搜尋title欄位。假如我需要同時搜尋title和description兩個欄位呢?身為一個搜尋功能,要搜尋所有文字資料也是很合理的。
因此,我們可以將controller的搜尋內容修改如下:
class ProductsController < ApplicationController
def index
if params[:search]
@product = Product.where('title LIKE ? OR description LIKE ?', "%#{params[:search]}%", "%#{params[:search]}%")
else
@product = Product.all
end
end
end
看到哪裡不同了嗎?在where後方跟著的句法,變得有點長,因為我們設定了同時搜尋title和description兩個項目,中間加了一個OR,代表只要有一個地方符合,就會出現在搜尋結果中,而後方一次重複的"%#{params[:search]}%"則是因為針對description進行了同樣的搜尋,所以在後方也重複出現。
希望大家都設定成功喔!
(圖片來源:Sean MacEntee)