Atomフィード

2007年1月2日

(サム・ルービーに説得され、日付に秒単位の精度を使用することにしました。)

このブリキを始めたのは、バンガロールへのフライト中でした。シンプルであるという理由で、フィードにRSS 0.91を使用することに決めました。例(PragDaveのもの)を見れば、簡単にXMLを作成し、その機能を提供することができました。それはうまく機能しましたが、投稿に日付がないという苦情が時々寄せられます。

ThoughtBlogsの運営を維持しているエイデ・オシニエにアドバイスを求めました。彼は、RSS 0.91を使い続けるか、新しいフォーマット(そしてどれを選ぶか)について、慎重に検討した理由を1ページにわたって説明してくれました。最終的に、彼のより熱意のこもった結論に従いました。「頼むから、Atomを使ってくれ」と。

要するに、今ではAtomフィードを持っています。RSS 0.91フィードもまだありますが、メンテナンスのために作業が必要になった場合は、すぐに削除します。ですから、可能であればAtomフィードに切り替えることをお勧めします。ウェブページの参照を更新しましたが、現在名前の悪いRssFeedsページにもあります。

以下は、変換に関するいくつかの経験と考察です。

クリスマス休暇中に、Atomに関する情報をできる限り調べました。最初に考えたのは、Rubyライブラリを見つけて使うことでした。Rubyには、FeedToolsという非常に洗練されたフィード処理ライブラリがあります。フィードを作成できると主張していましたし、そうだと思います。しかし、すべてのドキュメントは、フィードの消費と変換、データベースへのキャッシングなどに関するものでした。多くの依存関係が導入され、フィードの作成だけに使う方法が明確ではありませんでした。

そこで、自分でXMLファイルを作成することにしました。結局のところ、これはRubyでは非常に簡単です。特に、素晴らしいbuilderライブラリがある今ではなおさらです。

そこで次の課題は、Atomファイルがどのような見た目で、各部分が何を意味するのかを理解することでした。3つのことが非常に役に立ちました。

  • 私のような人間は、常に現実の例を求めます。サム・ルービーフィードが良い例になるはずです。
  • エイデがAtomを支持した大きな理由の1つは、堅牢な仕様です。ほとんどの仕様と同様に、必要な質問に答えるためにざっと目を通しました。一般的に、私は例から始めて、それが機能するまで徐々に調整し、問題が発生したときに仕様を参照することを好みます。これは典型的なバカの行動です。
  • おそらくAtomを使用する最良の理由は、優れたテストフレームワークであるfeedvalidatorです。これは非常に役立つことがわかりました。

私は3つのフィードに取り組んでいます。更新フィード、ブリキフィード、refactoring.comのフィードです。フィードのデータは異なるフォーマットから取得されたため、これは一般的なものの、ある任意のフォーマットから別の任意のフォーマットへのデータ変換という退屈な作業でした。エンタープライズソフトウェアの多くはこれと同じようなものであり、楽しい部分ではありません。

ゲートウェイとして機能する独自のフィードオブジェクトとエントリオブジェクトを作成することから始めました。このようにして、3つの変換にとって意味のあるオブジェクトにプログラムすることができ、XML変換やAtom特有の奇妙な点を1か所にまとめておくことができました。最初は、これが本当に価値があるのかどうか疑問に思いました。結局のところ、builderは非常に使いやすいからです。すぐにそれが価値のあることだとわかりました。

プロセスのほとんどは非常に簡単でした。RSSフィードを作成した方法を見て、Atomフィードでも同じことをしました。(はい、古いRSSフィードにもゲートウェイを使用するべきだったことを知っています。私も愚かになれるのです。)難しい点は、Atomフィードに新しく追加された点に関するものでした。

その最初のものはIDです。Atomでは、各エントリにIDを付けることが必須です。これにより、アグリゲーターは、異なるソースから取得された同じエントリの複数のコピーを見つけるのが容易になり、新しいエントリが真に新しいエントリなのか、更新された古いエントリなのかを判断することも容易になります。私のブリキでは、IDを選択するのは簡単でした。エントリはウェブブリキのエントリと正確に対応しているので、ブリキエントリのURLを使用しました。

ニュースの更新には、特定のページがありません。サム・ルービーのページを見て、彼はタグを使用していることに気づきました。これは私にとって新しいものでしたが、Google検索で説明を見つけました。私のドメイン名と日付でタグを生成し、サム・ルービーを再びコピーしてタイトルからテキストをクリーンアップしました。

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というまさに必要なメソッドがあることに気づきました。

仕様で明確ではなかったのは、更新日とは実際に何を意味するのかということです。仕様では単に「エントリまたはフィードが発行者にとって重要な方法で変更された最新の時点」と述べられています。ブリキのエントリを変更する場合は、タイプミスを修正するか、エントリを何らかの方法で改訂することです。タイプミスは重要とは考えていません。アグリゲーターがエントリの自分のコピーを更新することを期待していますが、新規または変更として強調表示することを期待していません。後者の変更は強調表示されることを期待しています。仕様で、アグリゲーターと読者が日付をどのように解釈するかについての提案があれば役に立ったでしょう。結局のところ、その解釈がフィールドの真の意味を伝えます。この問題はよく見かけます。仕様の執筆者は、クライアントを制約したくないため、クライアントが何をするべきかという標準を仕様に含めることをためらいます。その懸念は理解できますが、いくつかのシナリオを使用して、どのように使用されるかを想像していることを示すことは非常に役立つと思います。

更新日の最も厄介な点は、更新日の精度です。Atomの仕様では、「日付の値は可能な限り正確にする必要があります。たとえば、発行システムが1日の間に公開された複数のエントリに同じタイムスタンプを適用することは、一般的に不適切です。」と述べられています。しかし、私は自分の更新を日付の精度を持つものとして見てきました。エントリをサーバーにアップロードする時間は私にとって重要ではなく、どの日にそれを行ったかだけが重要です。したがって、私のタイムスタンプはそれを反映しています。日付のみが記載されており(実際には日付の精度であるRubyのDateクラスを使用しています)。

最初は、RFC 3339を満たすために時間部分に任意の00:00Zを選択して、日付の精度でそのままにしておくことを考えました。「べき」ではなく「する」とAtomの仕様に記載されていたことは、StandardsSpeakでは重要な違いであり、feedvalidatorは、同じタイムスタンプを持つ2つのエントリをエラーではなく警告としてマークしました。下流の問題を理解しない限り、日付の精度ではなく秒単位の精度の更新を処理するための作業を行う理由が見当たりませんでした。

サム・ルービーは説得力のあるシナリオを提供しました。彼自身を含め、一部の人々は複数のフィードを集約し、最新のものから始めて、以前に読んだものを読むまでさかのぼって読んでいます。私のエントリは通常、想定される時間ログよりも早く挿入され、読まれませんでした。(リストの一番上に保持するために任意の遅い時間部分を与えることができますが、それは読者をイライラさせるだけです。)

そこで、秒単位の精度を使用することにしました。タイムスタンプを処理するために使用していたDateオブジェクトをRubyのTimeオブジェクトに置き換える必要がありました。また、投稿に完全な時間を記載する必要があり、このエントリ以降はそうします。

フィードを徐々に完成させていくにつれて、feedvalidatorをダウンロードしてフィードをテストしました。apt-getを使用するだけで済むのではなく、実際にはrawをインストールする必要があり、顔をしかめましたが、甘えているのかもしれません。

最後に、ちょっとした話をしましょう。1、2年前、非常に大きなソフトウェア会社(あなたが知っているソフトウェアを製造している会社です)から、私のフィードを彼らが作成しているアーキテクチャフィードに集約しても構わないかと尋ねられました。私のいつものように、「構いません、それがフィードの目的です」と答えました。1、2か月後、私のフィードを使用できず、RSS 2.0に変更する必要があるというメールが届きました。それは私がやりたがるよりも多くの労力だったので、断りました。しかし、この大企業が明らかにこの作業を行うために本格的なプロジェクトを立ち上げているのに、エイデが自分の時間で私たちのためにやっていることさえできないことに、思わず笑ってしまいました。