#author("2017-05-15T13:47:42+09:00","default:wikiwriter","wikiwriter")
#author("2017-05-15T15:53:45+09:00","default:wikiwriter","wikiwriter")
&tag(Feedjira/解析);
*目次 [#if9db217]
#contents
*関連ページ [#d7cf3a70]
*参考情報 [#f57d2dc0]

*処理の流れ [#ce746af8]
- 通常以下のメソッドの呼び出しによってfeedが取得できる。
 feed = Feedjira::Feed.fetch_and_parse(feed_url)
-メソッドはfeedjira/feed.rbに存在。
#pre{{
      def fetch_and_parse(url)
        response = connection(url).get
        unless response.success?
          raise FetchFailure, "Fetch failed - #{response.status}"
        end
        feed = parse response.body #レスポンスを解析
        feed.feed_url = url
        feed.etag = response.headers['etag'].to_s.delete '"'

        feed.last_modified = parse_last_modified(response)
        feed
      end
}}
-parseはFeedクラスのクラスメソッドで以下のような内容となっている(同ファイル)。
#pre{{
      def parse(xml, &block)
        parser = determine_feed_parser_for_xml(xml)
        raise NoParserAvailable, 'No valid parser for XML.' unless parser
        parse_with parser, xml, &block
      end
}}
-実際のparserはURLの取得先によって切り替わる。パーサーの配列はconfiguration.rbで以下のような種類が準備されている。
#pre{{
    # @private
    def default_parsers
      [
        Feedjira::Parser::RSSFeedBurner,
        Feedjira::Parser::GoogleDocsAtom,
        Feedjira::Parser::AtomYoutube,
        Feedjira::Parser::AtomFeedBurner,
        Feedjira::Parser::Atom,
        Feedjira::Parser::ITunesRSS,
        Feedjira::Parser::RSS
      ]
    end
  end
}}
-rssの場合は、parser/rss.rbがそれ。
#pre{{
# rubocop:disable Style/DocumentationMethod
module Feedjira
  module Parser
    # Parser for dealing with RSS feeds.
    # Source: https://cyber.harvard.edu/rss/rss.html
    class RSS
      include SAXMachine
      include FeedUtilities
      element :description
      element :image, class: RSSImage
      element :language
      element :lastBuildDate, as: :last_built
      element :link, as: :url
      element :rss, as: :version, value: :version
      element :title
      element :ttl
      elements :"atom:link", as: :hubs, value: :href, with: { rel: 'hub' }
      elements :item, as: :entries, class: RSSEntry

      attr_accessor :feed_url

      def self.able_to_parse?(xml)
        (/\<rss|\<rdf/ =~ xml) && !(/feedburner/ =~ xml)
      end
    end
  end
end

}}
-ParserにSAXMachineとFeedUtilitiesがincludeされていることに注意。SAXMachineは外部gemで、FeedUtilitiesはFeedjira内部のmoduleとなっている(moduleによってnew_entries, update, last_modifiedなどのメソッドが追加されている)。parseはSAXMachineのparseメソッドが呼び出される。
-parseの戻り値は自身のクラスFeedjira::Parser::RSSとなる。

*ポイント [#k74d9d20]
**last_modifiedはどこで設定される [#yf4e67f0]
-fetch_and_parse内部のfeed = parse response.bodyの呼び出し直後にすでに@last_modifiedが設定されている。

-fetch_and_parse内部のfeed = parse response.bodyの呼び出し直後にすでに@last_modifiedが設定されている。=>と思ったのは間違いでデバッガのwatchによって、feed.last_modifiedが評価されたタイミングで@last_modifiedに値が設定されていたのが原因っぽい。
-@last_modifiedはSAX Machineではなくて、FeedUtilitiesで定義される通常のアクセサメソッドで、以下のようにgetterが定義されている。
#pre{{
    def last_modified
      puts "hereherehere"
      @last_modified ||= begin
        published = entries.reject { |e| e.published.nil? }
        entry = published.sort_by { |e| e.published if e.published }.last
        entry ? entry.published : nil
      end
    end
}}
-すなわち@last_modifiedがnilの場合、フィードに含まれるエントリーの最後のpublishedが採用されることがわかる。

トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS