lib/atom/feed.rb in atom-tools-1.0.0 vs lib/atom/feed.rb in atom-tools-2.0.0
- old
+ new
@@ -19,70 +19,58 @@
# subtitle:: a human-readable description or subtitle (Atom::Text)
# updated:: the most recent Time the feed was modified in a way the publisher considers significant
# generator:: the agent used to generate a feed
# icon:: an IRI identifying an icon which visually identifies a feed (1:1 aspect ratio, looks OK small)
# logo:: an IRI identifying an image which visually identifies a feed (2:1 aspect ratio)
- # rights:: rights held in and over a feed (Atom::Text)
+ # rights:: rights held in and over a feed (Atom::Text)
#
- # There are also +links+, +categories+, +authors+, +contributors+
+ # There are also +links+, +categories+, +authors+, +contributors+
# and +entries+, each of which is an Array of its respective type and
# can be used thusly:
#
# entry = feed.entries.new
# entry.title = "blah blah blah"
+ #
class Feed < Atom::Element
+ is_atom_element :feed
+
attr_reader :uri
# the Atom::Feed pointed to by link[@rel='previous']
attr_reader :prev
# the Atom::Feed pointed to by link[@rel='next']
attr_reader :next
-
+
# conditional get information from the last fetch
attr_reader :etag, :last_modified
- element :id, String, true
- element :title, Atom::Text, true
- element :subtitle, Atom::Text
-
- element :updated, Atom::Time, true
+ atom_string :id
+ atom_element :title, Atom::Title
+ atom_element :subtitle, Atom::Subtitle
- element :links, Atom::Multiple(Atom::Link)
- element :categories, Atom::Multiple(Atom::Category)
+ atom_time :updated
- element :authors, Atom::Multiple(Atom::Author)
- element :contributors, Atom::Multiple(Atom::Contributor)
+ include HasLinks
+ include HasCategories
- element :generator, String # XXX with uri and version attributes!
- element :icon, String
- element :logo, String
+ atom_elements :author, :authors, Atom::Author
+ atom_elements :contributor, :contributors, Atom::Contributor
- element :rights, Atom::Text
-
- element :entries, Atom::Multiple(Atom::Entry)
+ atom_string :generator # XXX with uri and version attributes!
+ atom_string :icon
+ atom_string :logo
+ atom_element :rights, Atom::Rights
+
+ atom_elements :entry, :entries, Atom::Entry
+
include Enumerable
def inspect # :nodoc:
"<#{@uri} entries: #{entries.length} title='#{title}'>"
end
- # parses XML fetched from +base+ into an Atom::Feed
- def self.parse xml, base = ""
- if xml.respond_to? :to_atom_entry
- xml.to_atom_feed(base)
- elsif xml.respond_to? :read
- self.parse(xml.read)
- else
- begin
- REXML::Document.new(xml.to_s).to_atom_feed(base)
- rescue REXML::ParseException
- raise Atom::ParseError
- end
- end
- end
-
# Create a new Feed that can be found at feed_uri and retrieved
# using an Atom::HTTP object http
def initialize feed_uri = nil, http = Atom::HTTP.new
@entries = []
@http = http
@@ -90,11 +78,11 @@
if feed_uri
@uri = feed_uri.to_uri
self.base = feed_uri
end
- super "feed"
+ super()
end
# iterates over a feed's entries
def each &block
@entries.each &block
@@ -106,11 +94,11 @@
# gets everything in the logical feed (could be a lot of stuff)
# (see <http://www.ietf.org/internet-drafts/draft-nottingham-atompub-feed-history-05.txt>)
def get_everything!
self.update!
-
+
prev = @prev
while prev
prev.update!
self.merge_entries! prev
@@ -134,65 +122,63 @@
# TODO: add atom:source elements
self << entry
end
end
- # like #merge, but in place
+ # like #merge, but in place
def merge! other_feed
- [:id, :title, :subtitle, :updated, :rights, :logo, :icon].each { |p|
- self.send("#{p}=", other_feed.send("#{p}"))
- }
+ [:id, :title, :subtitle, :updated, :rights, :logo, :icon].each do |p|
+ if (v = other_feed.get(p))
+ set p, v
+ end
+ end
[:links, :categories, :authors, :contributors].each do |p|
- other_feed.send("#{p}").each do |e|
- self.send("#{p}") << e
+ other_feed.get(p).each do |e|
+ get(p) << e
end
end
+ @extensions = other_feed.extensions
+
merge_entries! other_feed
end
# merges "important" properties of this feed with another one,
# returning a new feed
def merge other_feed
feed = self.clone
feed.merge! other_feed
-
+
feed
end
# fetches this feed's URL, parses the result and #merge!s
# changes, new entries, &c.
#
# (note that this is different from Atom::Entry#updated!
def update!
raise(RuntimeError, "can't fetch without a uri.") unless @uri
-
- headers = {}
- headers["Accept"] = "application/atom+xml"
- headers["If-None-Match"] = @etag if @etag
- headers["If-Modified-Since"] = @last_modified if @last_modified
- res = @http.get(@uri, headers)
+ res = @http.get(@uri, "Accept" => "application/atom+xml")
- if res.code == "304"
+ if @etag and res['etag'] == @etag
# we're already all up to date
return self
elsif res.code == "410"
raise Atom::FeedGone, "410 Gone (#{@uri})"
elsif res.code != "200"
raise Atom::HTTPException, "Unexpected HTTP response code: #{res.code}"
end
-
+
# we'll be forgiving about feed content types.
- res.validate_content_type(["application/atom+xml",
- "application/xml",
+ res.validate_content_type(["application/atom+xml",
+ "application/xml",
"text/xml"])
@etag = res["ETag"] if res["ETag"]
- @last_modified = res["Last-Modified"] if res["Last-Modified"]
xml = res.body
coll = REXML::Document.new(xml)
@@ -201,29 +187,28 @@
# the feed hasn't been updated, don't do anything.
if update_el and self.updated and self.updated >= Time.parse(update_el.text)
return self
end
- coll = Atom::Feed.parse(coll, self.base.to_s)
+ coll = self.class.parse(coll.root, self.base.to_s)
merge! coll
- link = coll.links.find { |l| l["rel"] == "next" and l["type"] == "application/atom+xml" }
- if link
- abs_uri = @uri + link["href"]
- @next = Feed.new(abs_uri.to_s, @http)
+ if abs_uri = next_link
+ @next = self.class.new(abs_uri.to_s, @http)
end
- link = coll.links.find { |l| l["rel"] == "previous" and l["type"] == "application/atom+xml" }
- if link
- abs_uri = @uri + link["href"]
- @prev = Feed.new(abs_uri.to_s, @http)
+ if abs_uri = previous_link
+ @prev = self.class.new(abs_uri.to_s, @http)
end
self
end
- # adds an entry to this feed. if this feed already contains an
+ atom_link :previous_link, :rel => 'previous'
+ atom_link :next_link, :rel => 'next'
+
+ # adds an entry to this feed. if this feed already contains an
# entry with the same id, the newest one is used.
def << entry
existing = entries.find do |e|
e.id == entry.id
end
@@ -234,8 +219,5 @@
@entries[@entries.index(existing)] = entry
end
end
end
end
-
-# this is here solely so you don't have to require it
-require "atom/xml"