Nic Lin's Blog

喜歡在地上滾的工程師

使用 Friendly_id 與 Babosa 美化你的Rails 網址

Rails App 一般是使用資料庫裡的每筆資料id作為網址連結,例如 http://example.com/product/1,然而這樣的網址是沒有意義的,對資料庫來說就只是一個遞增的數字,對使用者而言也只是個不知為何的數字,所以我們用FriendlyId這隻gem來客製化我們的網址,他的運作原理是讓 ActiveRecord 產生 Slug ,並將他做為 Record的識別。 使用前 http://example.com/product/4323454 使用後 http://example.com/product/aeron-chair

如果每筆資料的slug是唯一的,就可以利用http://example.com/product/aeron-chair來讀取到你的record。

Gem的設定

# rails4以上版本要裝5.0.0以上的friendly_id
gem 'friendly_id', '~> 5.0.0'

# babosa這個gem是讓我們做字元轉換的,支援中文網址
# 例如:http://example.com/product/阿龍椅
gem "babosa"

建立必要的資料表

rails generate friendly_id
rails generate migration add_slug_to_products slug:string:uniq
rake db:migrate

資料表建立完成後在Produc Model下進行設定

class Product < ActiveRecord::Base
  extend FriendlyId
  friendly_id :name, use: :slugged
end

這裡的friendly_id設定name的意思是指說,將原本網址對應到的 :id 變成直接對應該product model裡面的 :name 欄位

接下來的作法是在有用到 Product.find(params[:id]) 的地方將其修改為 Product.friendly.find(params[:id])

可是如果有一百個地方都用到呢?那豈不是要全改? 也許你可以這樣做

    #將以下這行原先的註解拿掉
    config.use :finders

這樣一來直接用原本的Product.find(params[:id]) 就會自動指向你所設定的 :name

到目前這個步驟應該成功將無意義的網址變成顯示product name的網址了

如果舊資料沒有slug怎麼辦呢?

舊有的資料如果沒有slug會一樣用原本的:id去執行,總不能手動一個一個改! 所以我們先進rails console

輸入Product.find_each(&:save), 這裡的Product請替換成你要做slug的table!

解決中文產生出亂碼網址

如果你的name欄位是英文數字,在顯示上是沒問題的,但一遇到中文,他會因為該Gem所使用到 ActiveSupport 的 parameterize,把非 a-z,0-9,- 的字元全部變成 -,於是中文字就會被吃掉了,然後輸出預設的UUID格式,像是2bc08962-b3dd-4f29-b2e6-244710c86106這樣的東西。

為了解決中文無法顯示的困擾,我們在前面有提到這隻Gembabosa,他可以把 UTF-8 字元處理好,而不是都消滅,跟 FriendlyId 配合只要把 normalize_friendly_id override 就可以了

class Product < ActiveRecord::Base
  extend FriendlyId
  # 把原先的:name改成:slug_candidates
  friendly_id :slug_candidates, use: :slugged
  
  # 原本是input.to_s.parameterize,但是parameterize只支援英文跟數字,所以改用babosa的to_slug
  def normalize_friendly_id(input)
    input.to_s.to_slug.normalize.to_s
  end
  
  # 定義slug_candidates,預設會找第一個,如果有重複的name就會找第二個(name-price),最後才會生成亂序
  def slug_candidates
    [
      :name,
      [:name, :price]
    ]
  end
end

參考來源: 使用 Babosa 配合 Friendly_id 解決中文網址問題 Rails讓網址不再只顯示ID

comments powered by Disqus