Class Atom::Feed
In: lib/atom/feed.rb
Parent: Atom::Element

A feed of entries. As an Atom::Element, it can be manipulated using accessors for each of its child elements. You can set them with any object that makes sense; they will be returned in the types listed.

Feeds have the following children:

id:a universally unique IRI which permanently identifies the feed
title:a human-readable title (Atom::Text)
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)

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"

Methods

<<   each   get_everything!   merge   merge!   merge_entries!   new   parse   update!  

Included Modules

Enumerable

Attributes

etag  [R]  conditional get information from the last fetch
last_modified  [R]  conditional get information from the last fetch
next  [R]  the Atom::Feed pointed to by link[@rel=‘next’]
prev  [R]  the Atom::Feed pointed to by link[@rel=‘previous’]
uri  [R] 

Public Class methods

Create a new Feed that can be found at feed_uri and retrieved using an Atom::HTTP object http

[Source]

    # File lib/atom/feed.rb, line 82
82:     def initialize feed_uri = nil, http = Atom::HTTP.new
83:       @entries = []
84:       @http = http
85: 
86:       if feed_uri
87:         @uri = feed_uri.to_uri
88:         self.base = feed_uri
89:       end
90: 
91:       super "feed"
92:     end

parses XML fetched from base into an Atom::Feed

[Source]

    # File lib/atom/feed.rb, line 70
70:     def self.parse xml, base = ""
71:       if xml.respond_to? :to_atom_entry
72:         xml.to_atom_feed(base)
73:       elsif xml.respond_to? :read
74:         self.parse(xml.read)
75:       else
76:         REXML::Document.new(xml.to_s).to_atom_feed(base)
77:       end
78:     end

Public Instance methods

adds an entry to this feed. if this feed already contains an entry with the same id, the newest one is used.

[Source]

     # File lib/atom/feed.rb, line 218
218:     def << entry
219:       existing = entries.find do |e|
220:         e.id == entry.id
221:       end
222: 
223:       if not existing
224:         @entries << entry
225:       elsif not existing.updated or (existing.updated and entry.updated and entry.updated >= existing.updated)
226:         @entries[@entries.index(existing)] = entry
227:       end
228:     end

iterates over a feed‘s entries

[Source]

    # File lib/atom/feed.rb, line 95
95:     def each &block
96:       @entries.each &block
97:     end

gets everything in the logical feed (could be a lot of stuff) (see <www.ietf.org/internet-drafts/draft-nottingham-atompub-feed-history-05.txt>)

[Source]

     # File lib/atom/feed.rb, line 101
101:     def get_everything!
102:       self.update!
103:   
104:       prev = @prev
105:       while prev
106:         prev.update!
107: 
108:         self.merge_entries! prev
109:         prev = prev.prev
110:       end
111: 
112:       nxt = @next
113:       while nxt
114:         nxt.update!
115: 
116:         self.merge_entries! nxt
117:         nxt = nxt.next
118:       end
119: 
120:       self
121:     end

merges "important" properties of this feed with another one, returning a new feed

[Source]

     # File lib/atom/feed.rb, line 148
148:     def merge other_feed
149:       feed = self.clone
150: 
151:       feed.merge! other_feed
152:       
153:       feed
154:     end

like merge, but in place

[Source]

     # File lib/atom/feed.rb, line 132
132:     def merge! other_feed
133:       [:id, :title, :subtitle, :updated, :rights].each { |p|
134:         self.send("#{p}=", other_feed.send("#{p}"))
135:       }
136: 
137:       [:links, :categories, :authors, :contributors].each do |p|
138:         other_feed.send("#{p}").each do |e|
139:           self.send("#{p}") << e
140:         end
141:       end
142: 
143:       merge_entries! other_feed
144:     end

merges the entries from another feed into this one

[Source]

     # File lib/atom/feed.rb, line 124
124:     def merge_entries! other_feed
125:       other_feed.each do |entry|
126:         # TODO: add atom:source elements
127:         self << entry
128:       end
129:     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!

[Source]

     # File lib/atom/feed.rb, line 160
160:     def update!
161:       raise(RuntimeError, "can't fetch without a uri.") unless @uri
162:      
163:       headers = {}
164:       headers["Accept"] = "application/atom+xml"
165:       headers["If-None-Match"] = @etag if @etag
166:       headers["If-Modified-Since"] = @last_modified if @last_modified
167: 
168:       res = @http.get(@uri, headers)
169: 
170:       # we'll be forgiving about feed content types.
171:       res.validate_content_type(["application/atom+xml", 
172:                                   "application/xml", 
173:                                   "text/xml"])
174: 
175:       if res.code == "304"
176:         # we're already all up to date
177:         return self
178:       elsif res.code == "410"
179:         raise Atom::FeedGone, "410 Gone (#{@uri})"
180:       elsif res.code != "200"
181:         raise Atom::HTTPException, "Unexpected HTTP response code: #{res.code}"
182:       end
183:        
184:       @etag = res["Etag"] if res["Etag"]
185:       @last_modified = res["Last-Modified"] if res["Last-Modified"]
186: 
187:       xml = res.body
188: 
189:       coll = REXML::Document.new(xml)
190: 
191:       update_el = REXML::XPath.first(coll, "/atom:feed/atom:updated", { "atom" => Atom::NS } )
192: 
193:       # the feed hasn't been updated, don't do anything.
194:       if update_el and self.updated and self.updated >= Time.parse(update_el.text)
195:         return self
196:       end
197: 
198:       coll = Atom::Feed.parse(coll, self.base.to_s)
199:       merge! coll
200:      
201:       link = coll.links.find { |l| l["rel"] = "next" and l["type"] == "application/atom+xml" }
202:       if link
203:         abs_uri = @uri + link["href"]
204:         @next = Feed.new(abs_uri.to_s, @http)
205:       end
206: 
207:       link = coll.links.find { |l| l["rel"] = "previous" and l["type"] == "application/atom+xml" } 
208:       if link
209:         abs_uri = @uri + link["href"]
210:         @prev = Feed.new(abs_uri.to_s, @http)
211:       end
212: 
213:       self
214:     end

[Validate]