#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が採用されることがわかる。