Class: Atom::Feed

Inherits:
Element show all
Includes:
HasCategories, HasLinks, Enumerable
Defined in:
lib/atom/feed.rb,
lib/atom/entry.rb

Overview

this is just a forward declaration since atom/entry includes atom/feed and vice-versa.

Direct Known Subclasses

Source

Instance Attribute Summary collapse

Attributes inherited from Element

#base, #extensions

Instance Method Summary collapse

Methods included from HasCategories

included, #tag_with

Methods included from HasLinks

#find_link, included

Methods inherited from Element

#append_elem, attributes, #build, builders, def_get, def_set, do_parsing, #get, #get_atom_attrb, #get_atom_elem, #get_atom_elems, #get_elem, #get_elems, is_atom_element, is_element, on_build, on_init, parse, run_initters, #set, #set_atom_attrb, #to_s, #to_xml

Methods included from Converters

#atom_attrb, #atom_element, #atom_elements, #atom_link, #atom_string, #atom_time, #attrb, #build_plain, #element, #elements, #strings, #time

Methods included from Parsers

#on_parse, #on_parse_attr, #on_parse_many, #on_parse_root, #parse_plain

Constructor Details

#initialize(feed_uri = nil, http = Atom::HTTP.new) ⇒ Feed

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


78
79
80
81
82
83
84
85
86
87
88
# File 'lib/atom/feed.rb', line 78

def initialize feed_uri = nil, http = Atom::HTTP.new
  @entries = []
  @http = http

  if feed_uri
    @uri = feed_uri.to_uri
    self.base = feed_uri
  end

  super()
end

Instance Attribute Details

#etagObject (readonly)

conditional get information from the last fetch


48
49
50
# File 'lib/atom/feed.rb', line 48

def etag
  @etag
end

#last_modifiedObject (readonly)

conditional get information from the last fetch


48
49
50
# File 'lib/atom/feed.rb', line 48

def last_modified
  @last_modified
end

#nextObject (readonly)

the Atom::Feed pointed to by link


45
46
47
# File 'lib/atom/feed.rb', line 45

def next
  @next
end

#prevObject (readonly)

the Atom::Feed pointed to by link


43
44
45
# File 'lib/atom/feed.rb', line 43

def prev
  @prev
end

#uriObject (readonly)

Returns the value of attribute uri


40
41
42
# File 'lib/atom/feed.rb', line 40

def uri
  @uri
end

Instance Method Details

#<<(entry) ⇒ Object

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


215
216
217
218
219
220
221
222
223
224
225
# File 'lib/atom/feed.rb', line 215

def << entry
  existing = entries.find do |e|
    e.id == entry.id
  end

  if not existing
    @entries << entry
  elsif not existing.updated or (existing.updated and entry.updated and entry.updated >= existing.updated)
    @entries[@entries.index(existing)] = entry
  end
end

#each(&block) ⇒ Object

iterates over a feed's entries


91
92
93
# File 'lib/atom/feed.rb', line 91

def each &block
  @entries.each &block
end

#empty?Boolean

Returns:

  • (Boolean)

95
96
97
# File 'lib/atom/feed.rb', line 95

def empty?
  @entries.empty?
end

#get_everything!Object

gets everything in the logical feed (could be a lot of stuff) (see RFC 5005)


101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/atom/feed.rb', line 101

def get_everything!
  self.update!

  prev = @prev
  while prev
    prev.update!

    self.merge_entries! prev
    prev = prev.prev
  end

  nxt = @next
  while nxt
    nxt.update!

    self.merge_entries! nxt
    nxt = nxt.next
  end

  self
end

#inspectObject

:nodoc:


72
73
74
# File 'lib/atom/feed.rb', line 72

def inspect # :nodoc:
  "<#{@uri} entries: #{entries.length} title='#{title}'>"
end

#merge(other_feed) ⇒ Object

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


152
153
154
155
156
157
158
# File 'lib/atom/feed.rb', line 152

def merge other_feed
  feed = self.clone

  feed.merge! other_feed

  feed
end

#merge!(other_feed) ⇒ Object

like #merge, but in place


132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/atom/feed.rb', line 132

def merge! other_feed
  [: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.get(p).each do |e|
      get(p) << e
    end
  end

  @extensions = other_feed.extensions

  merge_entries! other_feed
end

#merge_entries!(other_feed) ⇒ Object

merges the entries from another feed into this one


124
125
126
127
128
129
# File 'lib/atom/feed.rb', line 124

def merge_entries! other_feed
  other_feed.each do |entry|
    # TODO: add atom:source elements
    self << entry
  end
end

#update!Object

fetches this feed's URL, parses the result and #merge!s changes, new entries, &c.

(note that this is different from Atom::Entry#updated!

Raises:

  • (RuntimeError)

164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
# File 'lib/atom/feed.rb', line 164

def update!
  raise(RuntimeError, "can't fetch without a uri.") unless @uri

  res = @http.get(@uri, "Accept" => "application/atom+xml")

  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",
                              "text/xml"])

  @etag = res["ETag"] if res["ETag"]

  xml = res.body

  coll = REXML::Document.new(xml)

  update_el = REXML::XPath.first(coll, "/atom:feed/atom:updated", { "atom" => Atom::NS } )

  # 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 = self.class.parse(coll.root, self.base.to_s)
  merge! coll

  if abs_uri = next_link
    @next = self.class.new(abs_uri.to_s, @http)
  end

  if abs_uri = previous_link
    @prev = self.class.new(abs_uri.to_s, @http)
  end

  self
end