Atom 饋送
2007 年 1 月 2 日
(更新,因為 Sam Ruby 說服我對日期使用第二精確度。)
當我在飛往班加羅爾的航班上開始撰寫這個 wiki 時,我決定對我的饋送使用 RSS 0.91,理由是它很簡單。我所要做的就是看一個範例(碰巧是 PragDave 的),然後我就能輕鬆建立提供該功能的 XML。它對我來說很好用,但我偶爾會收到文章沒有標示日期的抱怨。
我請教了負責維護 ThoughtBlogs 的 Ade Oshineye。他給我一個頁面,仔細考量了維持 RSS 0.91 或選擇新格式(以及選擇哪一個格式)的理由。最後我採納了他更熱情的結論:「看在上帝的份上,請使用 Atom。」
言歸正傳,我現在有 atom 饋送。我仍然有 RSS 0.91 饋送,但如果我必須做任何工作來維護它們,我將會立即放棄它們。因此我建議您在可以的時候改用 atom 饋送。我已經更新了網頁上的參考,或者您可以在現在名稱不佳的 RssFeeds 頁面中找到它們。
以下是轉換的一些經驗和想法。
在聖誕節期間,我找出所有我能找到的關於 atom 的資訊。我的第一個想法是尋找並使用 Ruby 函式庫。Ruby 有個非常精密的饋送處理函式庫,稱為 FeedTools。它聲稱可以產生饋送,我相信它。然而,所有文件都是關於使用和轉換饋送、將它們快取在資料庫中,等等。它引入了許多依賴項,而且要如何僅使用它來建立饋送並不顯而易見。
因此我決定自己建立 XML 檔案。畢竟,這在 Ruby 中非常容易,特別是現在我們有了強大的 builder 函式庫。
因此,下一個技巧是要找出 atom 檔案的樣子,以及各部分的意義。我發現三件事對我很有幫助。
- 身為我,我總是想找一個真實的範例。我認為 Sam Ruby 的 饋送 應該是個很好的範例。
- Ade 提出支持 Atom 的一個重要原因是穩固的 規格。像大多數規格一樣,我瀏覽它以回答我需要解答的問題。一般來說,我比較喜歡從範例開始,然後逐漸調整它,直到它運作為止,遇到問題時再參考規格。這是 白癡 的典型行為。
- 使用 Atom 最好的原因可能是出色的測試架構:feedvalidator。我發現這非常有幫助。
我有三個要處理的饋送:我的更新饋送、我的 bliki 饋送和 refactoring.com 的饋送。這些饋送的資料來自不同的格式,因此這是從一種任意格式轉換到另一種格式的常見但繁瑣的資料轉換工作。許多企業軟體都是這樣,而且這不是有趣的部分。
我一開始建立自己的饋送和條目物件,作為 閘道。這樣,我就可以針對對我而言有意義的物件進行編寫程式,以進行這三種轉換,並將 XML 轉換和任何可能出現在一個地方的 Atom 怪異之處保留下來。一開始,我懷疑這是否值得,畢竟 builder 非常容易使用。我很快就發現它很值得。
大部分的流程都很直接。我只要查看我是如何建立 RSS 饋送,然後對 Atom 饋送執行相同的動作即可。(是的,我知道我應該對舊的 RSS 饋送使用閘道。我也會犯傻。)棘手的部分實際上是 Atom 饋送中的新事物。
第一個是 ID。Atom 堅持您為每個條目提供一個 ID。這讓匯總器更容易找出可能來自不同來源的同一個條目的多個副本,或者只是判斷一個新條目是真正的新條目還是已更新的舊條目。對於我的 bliki,選擇一個 ID 很容易 - 條目與 Web bliki 條目完全對應,所以我只使用了 bliki 條目的 URL。
對於新聞更新,沒有特定頁面。查看 Sam Ruby 的頁面,我看到他使用了標籤。這些對我來說很新,但透過 Google 搜尋找到了 說明。我使用我的網域名稱、日期和從標題中清理的文字產生標籤 - 再度複製自 Sam Ruby。
def calculate_atom_id specific = title.gsub(/\W/,'-') return "tag:#{domain_name},#{date.strftime("%Y-%m-%d")}:#{specific}" end
這樣做的真正驅動力是新增日期,這引入了幾個奇特之處。首先是 RFC 3339 日期,我必須查閱它才能了解它們如何運作。看起來 Ruby 日期類別沒有方法傳回 RFC 3339 日期,但在四處搜尋後,我發現 Time 類別有我需要的方法,也就是 Time.xmlschema。
規格中未明確說明更新日期的真正意義。規格僅表示為「發布者認為重要的,條目或摘要最近一次修改時間」。當我變更 bliki 條目時,可能是為了修正錯別字,或以某種方式修改條目。我不認為錯別字很重要。我確實希望彙總器更新條目的副本,但我並不希望他們將其標示為新的或已變更。我確實希望後續變更會被標示出來。如果規格提供一些建議,說明彙總器和讀取器如何詮釋日期,將會很有幫助,畢竟,這種詮釋傳達了欄位的真正意義。我經常發現這個問題,規格撰寫者不願意在標準中放入客戶端應執行的內容,因為他們不想限制客戶端。我了解這種考量,但我確實認為說明他們如何想像在某些情況下使用它會很有幫助。
對我來說,更新日期最尷尬的方面是更新日期的精確度。atom 規格指出「日期值應盡可能準確。例如,發布系統不應對在單日發布的多個條目套用相同時間戳記。」不過,我一直將我的更新視為具有日期精確度的內容。我上傳條目到伺服器的時間與我無關,我只關心我執行此動作的日期。因此,我的時間戳記反映了這一點,它們只提到日期(而且確實使用 Ruby 的 Date 類別,這是日期精確度)。
我最初的想法是將它們保留在日期精確度,選擇任意的 00:00Z 作為時間部分,以符合 RFC 3339。atom 規格使用「應」而非「必須」,這是 標準用語 中的重要區別,而 feedvalidator 將兩個具有相同時間戳記的條目標示為警告,而非錯誤。除非我能了解下游問題,否則我不明白我為何應投入工作來處理秒精確度更新,而非日期精確度。
Sam Ruby 提供了一個令人信服的場景。有些人(包括他在內)會彙總多個摘要,並從最新開始向後讀取,直到讀到他們之前讀過的部分。我的條目通常會比預期時間更早插入時間記錄中,而且不會被讀取。(我可以給它們一個任意的較晚時間部分,讓它們保持在清單頂端,但這只會讓讀者感到惱怒。)
因此我決定使用第二個精度。我需要用 Ruby 的 Time 物件取代我用來處理時間戳記的 Date 物件。我也需要開始在文章中放入完整時間,從這篇文章開始我會這麼做。
我下載了 feedvalidator 的一份副本,在我逐漸填寫時測試我的 feed。這很容易,雖然我對必須安裝 raw 而非僅使用 apt-get 而感到不悅,我想我變軟弱了。
最後一個額外的故事。一兩年前,一家非常大的軟體公司(一家我確定你很熟悉的軟體公司)問我是否介意將我的 feed 匯總到他們製作的架構 feed 中。我的回答,就像往常一樣,是「好,這就是 feed 的用途」。一兩個月後,我收到一封電子郵件,表示他們無法使用我的 feed,我需要將它改成 RSS 2.0。這比我想像中更費力,所以我拒絕了。但我忍不住竊笑,這個龐大的組織,顯然已經設立了一個全面的專案來執行這項工作,卻無法做到 Ade 在他的空閒時間為我們所做的事情。