惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V
V2EX
C
Check Point Blog
博客园_首页
B
Blog
D
Docker
U
Unit 42
量子位
I
InfoQ
有赞技术团队
有赞技术团队
Martin Fowler
Martin Fowler
GbyAI
GbyAI
L
LangChain Blog
云风的 BLOG
云风的 BLOG
博客园 - Franky
美团技术团队
T
The Blog of Author Tim Ferriss
阮一峰的网络日志
阮一峰的网络日志
月光博客
月光博客
Vercel News
Vercel News
Recent Announcements
Recent Announcements
雷峰网
雷峰网
大猫的无限游戏
大猫的无限游戏
小众软件
小众软件
Google DeepMind News
Google DeepMind News

Nic Lin's Blog

謝明真 - 高效領導力的課後筆記 NFT 開發實戰!基礎智能合約入門 (3) NFT 開發實戰!基礎智能合約入門 (2) NFT 開發實戰!基礎智能合約入門 (1) 如何自我檢測 log4j CVE 漏洞 Rails 如何在資料寫入時記錄來源 IP 位置 如何經營工程師 Youtube 頻道 - Part 8 營收篇 如何經營工程師 Youtube 頻道 - Part 7 酸民文化篇 如何經營工程師 Youtube 頻道 - Part 5 設備器材篇 如何經營工程師 Youtube 頻道 - Part 4 後製剪輯篇 如何經營工程師 Youtube 頻道 - Part 3 文案企劃篇 如何經營工程師 Youtube 頻道 - Part 2 設備器材篇 如何經營工程師 Youtube 頻道 - Part 1 制訂頻道方向篇 如何經營工程師 Youtube 頻道 - Part 0 Rails 中避免 race condition 的最佳實踐(二) Rails 中避免 race condition 的最佳實踐(一) 10 分鐘整合 google sheet 做自動化開發功能週報 經營 Side Project 300 天所帶來的收穫及挑戰 我的 Youtube 影片製作流程 API 設計時必須注意的 HTTP header 底線問題 如何提升你的程式可讀性之實務技巧(三) 如何提升你的程式可讀性之實務技巧(二) 如何提升你的程式可讀性之實務技巧(一) Ruby 中使用 freeze 優化效能的時機 避免 React 中的 useEffect 無限 render 在 Rails 內輕量使用 Vue Component 的最佳實踐 如何在區域網路用 Docker 架設有 SSL 的 Gitlab 從被問到問人,那些我常問的面試問題 [Rails] 如何漂亮寫出可維護的 query (Maintainable Rails Query) 在已知長度情況下優化 slice 的性能
[Rails] 用 Ransack 做搜尋功能
Nic Lin · 2017-08-10 · via Nic Lin's Blog

常見的情境有,搜索用戶資料、搜尋文章等等

而在 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