以 第3日 為例,常常網路上看到的網址是 http://SITE/blog/show/prison-break ,而不是 http://SITE/blog/show/2 ,使網址更具可讀性及意義;若不希望每篇文章或 user 的資料被 1..∞ 的順序被瀏覽的話,這是可以用 permalink 的方式來實現。
可參考 http://punk.tw/2007/10/06/340.html 的概念與作法,該文章中是以標題+時間進行md5的編碼做為 permalink ,是以保護不被以序號、流水號的方式被 try 出所有的資料出來,所以做出的 permalink ,人眼去讀是沒有意義的字碼;如果文章本來就是希望被讀、被 index 的話,其實是要讓網址具有可讀性,除非是像提供檔案下載的網址,不想通通全部被人都抓走,才不需要有可讀性及辨識性,才以編碼方式為名稱。而本文是要以可讀性為目標來設定:
新增 permalink 欄位
./script/generate migration AddPermalinkToArticle
# vi db/migrate/2008xxxxxxx_add_permalink_to_article.rb 修改成以下內容
class AddPermalinkToArticle < ActiveRecord::Migration
def self.up
add_column :articles, :permalink, :string
add_index :articles, :permalink
end
def self.down
remove_index :articles, :permalink
remove_column :articles, :permalink
end
end
# 再執行
rake db:migrate
測試 permalink 的語法
參考怎麼從文章的標題來做出 perlmalink 的語法 Permalink from post title ,透過以下指令來試驗一下:
./script/console
Loading development environment (Rails 2.1.1)
>> t = 'Prison Break'
=> "Prison Break"
>> t.downcase.gsub(/[^a-z0-9]+/,'-').to(127).gsub(/^-+|-+$/,'')
=> "prison-break"
上述的語法基本是,字串變小寫,不是字母及數字的字串,改為'-'符號連結,整個字串最長到127個字元,若是以'-'為最開始或結束,則砍掉最前最末的'-'符號。所以就可以簡化成這樣的語法來使用。
為現有的文章補 permalink 的值
可透過 ./script/console 來測試及直接將 permalink 的值補進去:
# 先測試一下語法是否可成功
>> Article.find(:all).each {|a| puts a.title.downcase.gsub(/[^a-z0-9]+/,'-').to(127).gsub(/^-+|-+$/,'') }
save-the-cheerleader-save-the-world
prison-break
..
=> [#<Article id: 1, title: "Save the Cheerleader, Save the World", body: ...
...
# 用這樣的語法就可以把現有文章的所有 permalink 重新補上
>> Article.find(:all).each {|a| a.permalink = a.title.downcase.gsub(/[^a-z0-9]+/,'-').to(127).gsub(/^-+|-+$/,''); a.save }
這樣原有的文章,原來 permalink 是空值的話,就都補上了。
網址唯一性的問題
但還要考慮的是,若不同的文章卻有同樣的標題,那不就會造成重覆的網址嗎?可參考 Model Name in URL 的作法,讓網址的參數是 id + permalink ,就不會有重覆的網址。
讓新增的文章自動加入 permalink
# 編輯 app/models/article.rb
class Article < ActiveRecord::Base
before_save :generate_permalink
def to_param
"#{id}-#{permalink}"
end
protected
def generate_permalink
self.permalink = self.title.downcase.gsub(/[^a-z0-9]+/,'-').to(127).gsub(/^-+|-+$/,'')
end
end
# 在 app/views/blog/index.html.erb 中的各文章連結改為
<%= link_to article.title, :action => 'show', :id => article -%>
這樣網址就會變成:http://SITE/blog/show/2-prison-break 即可連到各別文章,且是具有可讀性的網址了。然而用 http://SITE/blog/show/2 也還是看得到該文;就文章而言,是還好,但若是 user 的 profile 檔,就真的不希望這樣子就都被讀取到,所以若是 user 的 profile 的 show,就會以 find_by_username ,只能以 username 來查詢,而無法用 id 來查詢了。
但是在中文世界,大部份文章不都是以中文為標題?此法就不是那麼適用嗎?明天就來探索以中文來做 permalink 的方法。