simple-rss.rbのカスタマイズ

id:omochist:20060922:simplerss
の続き.

descriptionでNoMethodErrorが発生したらrescueしてtaglineを呼ぶ,とかするのは楽だろうけど,itemの方はnilが返ってきておるし….どーすりゃ良いんでしょうね.

って書いたけれど,この辺りはなんとか解決ができそう.

NoMethodErrorの対処

もしタグtaglineを追加したいのであれば,まずクラス変数feed_tagsにSymbolのtaglineを追加し,次にObject#method_missingをオーバーライドすることで対処できる.

  @@feed_tags = [
    :tagline,
    (略)]

  def method_missing(name, *arguments)
    if name.to_s =~ /description/
      self.send('tagline')
    else
      super
    end
  end

こんな感じのを書くと,インタフェースを統一できるよね.RDFでもAtomでも,rss.descriptionって呼べばそのフィードの概要を得られるということで.本格的に使うのなら,もっと条件分岐を増やすべきだろうけど.

itemの要素がnilの時の対処

以下の部分を変更する.

  def parse
    (略)
    # RSS items' title, link, and description
    (略)
      def item.method_missing(name, *args) self[name] end

の一番最後の行を,

      def item.method_missing(name, *args)
        if name.to_s =~ /description/ && self[name].nil?
          self[:summary]
        else
          self[name]
        end
      end

にするとか.こちらもコレでは不十分なので,もっと色々増やした方が良いのかな.でももっと良いのは,itemはHashなんだけれど,いっそItemクラスを作っちゃってmethod_missingを定義した方が良いと思うんだよね.

class Item < Hash # Hashを継承
  def method_missing(name, *args)
    if name.to_s =~ /description/ && self[name].nil?
      self[:summary]
    else
      self[name]
    end
  end
end

これぐらいしておけば,item要素を追加して幾たびにmethod_missingを定義しなくて済むし.なので,結局はsimple-rss.rbに上のItemの定義を追加して,

  def parse
    (略)
    # RSS items' title, link, and description
    @source.scan( %r{(長いので略)}mi ) do |match|
      item = Item.new # Hash.newをItem.newに
      @@item_tags.each do |tag|
        if match[3] =~ %r{<(rss:|atom:)?#{tag}(.*?)>(.*?)</(rss:|atom:)?#{tag}>}mi
          nil
        elsif match[3] =~ %r{<(rss:|atom:)?#{tag}(.*?)/\s*>}mi
          nil
        end
        item[clean_tag(tag)] = clean_content(tag, $2, $3) if $2 || $3
      end
      # def item.method_missing(name, args*) self[name] end を削除
      @items << item 
    end

にすれば良いかな.


だれか,もっとガッチリ作り直してくれないかしら.