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 72
72:     def self.parse xml, base = ""
73:       if xml.respond_to? :to_atom_entry
74:         xml.to_atom_feed(base)
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 214
214:     def << entry
215:       existing = entries.find do |e|
216:         e.id == entry.id
217:       end
218: 
219:       if not existing
220:         @entries << entry
221:       elsif not existing.updated or (existing.updated and entry.updated and entry.updated >= existing.updated)
222:         @entries[@entries.index(existing)] = entry
223:       end
224:     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.

[Source]

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

[Validate]