WebOS Goodies

WebOS の未来を模索する、ゲームプログラマあがりの Web 開発者のブログ。

WebOS Goodies へようこそ! WebOS はインターネットの未来形。あらゆる Web サイトが繋がり、共有し、協力して創り上げる、ひとつの巨大な情報システムです。そこでは、あらゆる情報がネットワーク上に蓄積され、我々はいつでも、どこからでも、多彩なデバイスを使ってそれらにアクセスできます。 WebOS Goodies は、さまざまな情報提供やツール開発を通して、そんな世界の実現に少しでも貢献するべく活動していきます。
Subscribe       

Rails で Atom / RSS フィードを生成する Builder テンプレート

Web サイトの更新を通知する Atom / RSS フィードは、現在の Web サイトになくてはならないもののひとつです。当然、 WebOS Goodies でも配信しているわけですが、独自 CMS に移行した際に、それらのフィードも自分で生成しなくてはならなくなりました。そこで、わりと汎用的に使える Builder テンプレートを作ってみたので、本日はそれをご紹介しようと思います。

一応、 Feed Validator で Valid の評価が貰えるようになっていますので、よろしければご利用ください。

ソースコード

まずはソースコードです。適当にコピペして使ってください。

こちらが Atom 用のテンプレート。

atom_feed(:language => 'ja-JP',
          :root_url => @site_url,
          :url      => @atom_url,
          :id       => @site_url) do |feed|
  feed.title    @site_title
  feed.subtitle @site_description
  feed.updated  Time.now
  feed.author{|author| author.name(@author) }
 
  @entries.each do |entry|
    feed.entry(entry,
               :url       => entry.url,
               :id        => entry.url,
               :published => entry.publish_date,
               :updated   => entry.updated_at) do |item|
      item.title(entry.title)
      item.content(entry.content, :type => 'html')
      item.author{|author| author.name(@author) }
    end
  end
end

そしてこちらが RSS 2.0 。

xml.instruct!
 
xml.rss("version"    => "2.0",
        "xmlns:dc"   => "http://purl.org/dc/elements/1.1/",
        "xmlns:atom" => "http://www.w3.org/2005/Atom") do
  xml.channel do
    xml.title       @site_title
    xml.link        @site_url
    xml.pubDate     Time.now.rfc822
    xml.description @site_description
    xml.atom :link, "href" => @rss_url, "rel" => "self", "type" => "application/rss+xml"
 
    @entries.each do |entry|
      xml.item do
        xml.title        entry.title
        xml.link         entry.url
        xml.guid         entry.url
        xml.description  entry.content
        xml.pubDate      entry.created_at.to_formatted_s(:rfc822)
        xml.dc :creator, @author
      end
    end
  end
end

使い方

基本的には、必要なテンプレートパラメータを設定して上記のテンプレートをレンダリングすれば、 Atom / RSS フィードが生成できます。必要なテンプレートパラメータと設定内容は以下のとおりです。

変数名 内容
@site_title サイトタイトル
@site_description サイトの説明、副題など
@site_url サイトの URL
@atom_url Atom フィードの URL
@rss_url RSS フィードの URL
@author サイト管理者の名前
@entries エントリデータの配列

@entries は各エントリ(ブログで言えばそれぞれの記事)の配列で、通常は ActiveRecord オブジェクトになるでしょう。必要なフィールドは以下のとおり。 created_at, updated_atDateTime 型でなければなりません。

メンバ名 内容
title エントリーのタイトル
url エントリーの URL
content エントリーの内容(HTML 形式)
created_at 公開日時
updated_at 更新日時

URL なんかは直接フィールドに入れるもんでもないかもしれませんが、その場合は適当にテンプレートを修正してください(^^;

ちなみに、フィードをレンダリングするアクションはそれぞれ個別に用意してもいいのですが、 respond_to を利用して切り替えることもできます。例えば、 Atom / RSS のテンプレートをそれぞれ "index.atom.builder", "index.rss.builder" というファイル名で保存しておき、サイトのトップページのアクションを以下のようにすれば OK です。

def index
  # 必要なテンプレートパラメータを設定
 
  respond_to do |type|
    type.html
    type.rss
    type.atom
  end
end

こうしておけば、 "/index" でアクセスされた場合にはリクエストヘッダの Accept-Type によって適切なテンプレートが選択され、 "/index.atom" なら Atom フィードが、 "/index.rss" なら RSS フィードが選択されます。こちらのほうが、より Rails らしい方法ですね。

おまけ : 日本語が文字参照に変換されるのを防ぐ

上記の方法でフィードを生成すると、ひとつ困った問題にぶちあたります。なぜか日本語がすべて文字参照に変換されてしまうのです。たしかに、このままでも動作に支障はないのですが、フィードのサイズが無駄に膨れ上がって嫌な感じです。

どうやらこの変換は Rails で拡張される String#to_xs というメソッドがやっているようなので、 environment.rb の最後で以下のように上書きすることで回避することができました。

class String
  def to_xs
    ERB::Util.h(unpack('U*').pack('U*')).gsub("'", ''') # ASCII, UTF-8
  rescue
    unpack('C*').map {|n| n.xchr}.join # ISO-8859-1, WIN-1252
  end
end

これにより、フィード以外でも Rails が生成するすべての XML で文字参照への変換が抑制されるはずです。かなり根っこの部分の変更なので影響範囲が心配ですが、軽く検索した限り XML の生成にしか使われていないので、まあ大丈夫でしょう。

以上、本日は Rails で Atom / RSS フィードを生成するテンプレートをご紹介しました。フィードは更新情報の配信以外にも、データのエクスポートやマッシュアップなどで幅広く利用されています。生成方法をおさえておけば必ず役に立つでしょう。ぜひご活用ください!

関連記事

この記事にコメントする

Recommendations
Books
「Closure Library」の入門書です。
詳しくはこちらの記事をどうぞ!
Categories
Recent Articles