[Rails] 讓 URL 不顯示 id 的方法 - via Friendly_id

目的

  本篇來記錄一下怎麼使用 Friendly_id 以及使用 Babosa 這兩個 gem 來達到美化 URL 的效果。

前言

  目前學習 Ruby on Rails 大約一個月半了,從學習的開始,打了一篇安裝文後,就被別的有趣的事情吸引去了,例如追韓劇、Running man、康熙、中國好聲音4、爸爸去哪兒3… 跑題了:P
  總而言之!現在開始使用 Logdown 作筆記跟分享,希望能幫助到需要的人。

筆記

1. Gem :

 先添加 gem 到 Gemfile 中

Gemfile
1
2
gem 'friendly_id', '~> 5.1.0'
gem 'babosa'

 記得在 console bundle 一下

1
bundle install

2. 生成資料表

 在 console 下

1
2
3
rails g friendly_id
rails g migration add_slug_to_users slug:string:uniq
rake db:migrate

 上面的 add_slug_to_users 意思是,加入一個 slug 欄位到資料表 User 中。

3. 撰寫 Model

app/models/user.rb
1
2
extend FriendlyId
friendly_id :name, use: :slugged

 以上,就完成單純使用 name 來當作路徑,若想自訂路徑格式,就來覆寫 normalize_friendly_id :

app/models/user.rb
1
2
3
def normalize_friendly_id(input)
input.to_s.to_slug.normalize.to_s
end

如果有使用 babosa gem 的話,就可以透過覆寫 normalize_friendly_id 支援中文囉!

4. Friendly.find

 這邊有兩個方法來讓 id 被 friendly 查找:

  • 修改 controller 中的 find

    app/controller/users_controller.rb
    1
    2
    @user = User.friendly.find(params[:id])
    # @user = User.find(params[:id])
  • 或是,將 config 中的 finder 功能打開:

    config/initializers/friendly_id.rb
    1
    config.use :finders # 把註解取消,啟動自動查找功能

以上,就完成功能囉!
如果已經有資料了,想直接更新 slug,就直接在 rails console 中執行:

1
User.find_each(&:save)

這樣就會自動把 slug 填上了!

2015.12.31 新增

若想讓 slug 隨著資料變更時作 update,我們可以透過定義 should_generate_new_friendly_id? 達到目的

app/models/user.rb
1
2
3
  def should_generate_new_friendly_id?
   slug.blank? || name_changed? # slug 為 nil 或 name column 變更時更新
  end

5. 補充

 如果想符合 SEO,可以在 normalize_friendly_id 裡定義路徑名稱,例如:

app/models/user.rb
1
2
3
def normalize_friendly_id(input)
"#{id}-#{input.to_s.to_slug.normalize.to_s}" # what ever you want
end

 以上面程式碼為例,路徑名稱就變成類似像 xxx/users/1-georgio
 另外,除了透過 friendly_id 去改變 url path 外,其實 rails 本身的解法是覆寫 model to_params method:

app/models/user.rb
1
2
3
def to_params
"#{id}-#{name}"
end

 就端看想用什麼方案解決囉 :D
 
That’s it, DONE!

【參考資料】