seangeo / ratom

A fast, libxml based, Ruby Atom library supporting the Syndication Format and the Publishing Protocol. <br> Gem is available now!!<br>

This URL has Read+Write access

ratom / README.txt
46e74293 » seangeo 2008-03-03 Added content to README. 1 = rAtom
2
3 rAtom is a library for working with the Atom Syndication Format and
4 the Atom Publishing Protocol (APP).
5
6 * Built using libxml so it is _much_ faster than a REXML based library.
7 * Uses the libxml pull parser so it has much lighter memory usage.
8 * Supports {RFC 5005}[http://www.ietf.org/rfc/rfc5005.txt] for feed pagination.
9
10 rAtom was originally built to support the communication between a number of applications
11 built by Peerworks[http://peerworks.org], via the Atom Publishing protocol. However, it
12 supports, or aims to support, all the Atom Syndication Format and Publication Protocol
13 and can be used to access Atom feeds or to script publishing entries to a blog supporting APP.
14
15 == Prerequisites
16
bf8c851a » seangeo 2009-03-19 17 * libxml-ruby, >= 1.1.2
46e74293 » seangeo 2008-03-03 Added content to README. 18 * rspec (Only required for tests)
19
20 libxml-ruby in turn requires the libxml2 library to be installed. libxml2 can be downloaded
21 from http://xmlsoft.org/downloads.html or installed using whatever tools are provided by your
22 platform. At least version 2.6.31 is required.
23
24 === Mac OSX
25
26 Mac OSX by default comes with an old version of libxml2 that will not work with rAtom. You
27 will need to install a more recent version. If you are using Macports:
28
29 port install libxml2
30
31 == Installation
32
33 You can install via gem using:
34
35 gem install ratom
36
37 == Usage
38
39 To fetch a parse an Atom Feed you can simply:
40
41 feed = Atom::Feed.load_feed(URI.parse("http://example.com/feed.atom"))
42
43 And then iterate over the entries in the feed using:
44
45 feed.each_entry do |entry|
46 # do cool stuff
47 end
48
da124144 » seangeo 2008-05-03 Better examples in the docu... 49 To construct the following example Feed is from the Atom spec:
46e74293 » seangeo 2008-03-03 Added content to README. 50
da124144 » seangeo 2008-05-03 Better examples in the docu... 51 <?xml version="1.0" encoding="utf-8"?>
52 <feed xmlns="http://www.w3.org/2005/Atom">
53
54 <title>Example Feed</title>
55 <link href="http://example.org/"/>
56 <updated>2003-12-13T18:30:02Z</updated>
57 <author>
58 <name>John Doe</name>
59 </author>
60 <id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
61
62 <entry>
63 <title>Atom-Powered Robots Run Amok</title>
64 <link href="http://example.org/2003/12/13/atom03"/>
65 <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
66 <updated>2003-12-13T18:30:02Z</updated>
67 <summary>Some text.</summary>
68 </entry>
69
70 </feed>
71
72 To build this in rAtom we would do:
73
74 feed = Atom::Feed.new do |f|
75 f.title = "Example Feed"
76 f.links << Atom::Link.new(:href => "http://example.org/")
77 f.updated = Time.parse('2003-12-13T18:30:02Z')
78 f.authors << Atom::Person.new(:name => 'John Doe')
79 f.id = "urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6"
80 f.entries << Atom::Entry.new do |e|
81 e.title = "Atom-Powered Robots Run Amok"
82 e.links << Atom::Link.new(:href => "http://example.org/2003/12/13/atom03")
83 e.id = "urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a"
84 e.updated = Time.parse('2003-12-13T18:30:02Z')
85 e.summary = "Some text."
86 end
46e74293 » seangeo 2008-03-03 Added content to README. 87 end
88
da124144 » seangeo 2008-05-03 Better examples in the docu... 89 To output the Feed as XML use to_xml
46e74293 » seangeo 2008-03-03 Added content to README. 90
91 > puts feed.to_xml
92 <?xml version="1.0"?>
93 <feed xmlns="http://www.w3.org/2005/Atom">
da124144 » seangeo 2008-05-03 Better examples in the docu... 94 <id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
95 <title>Example Feed</title>
96 <updated>2003-12-13T18:30:02Z</updated>
97 <link href="http://example.org/"/>
98 <author>
99 <name>John Doe</name>
100 </author>
101 <entry>
102 <title>Atom-Powered Robots Run Amok</title>
103 <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
104 <summary>Some text.</summary>
105 <updated>2003-12-13T18:30:02Z</updated>
106 <link href="http://example.org/2003/12/13/atom03"/>
107 </entry>
46e74293 » seangeo 2008-03-03 Added content to README. 108 </feed>
da124144 » seangeo 2008-05-03 Better examples in the docu... 109
46e74293 » seangeo 2008-03-03 Added content to README. 110
111 See Feed and Entry for details on the methods and attributes of those classes.
112
113 === Publishing
114
115 To publish to a remote feed using the Atom Publishing Protocol, first you need to create a collection to publish to:
116
117 require 'atom/pub'
118
119 collection = Atom::Pub::Collection.new(:href => 'http://example.org/myblog')
120
121 Then create a new entry
122
123 entry = Atom::Entry.new do |entry|
124 entry.title = "I have discovered rAtom"
125 entry.authors << Atom::Person.new(:name => 'A happy developer')
126 entry.updated = Time.now
127 entry.id = "http://example.org/myblog/newpost"
128 entry.content = Atom::Content::Html.new("<p>rAtom lets me post to my blog using Ruby, how cool!</p>")
129 end
130
131 And publish it to the Collection:
132
133 published_entry = collection.publish(entry)
134
135 Publish returns an updated entry filled out with any attributes to server may have set, including information
136 required to let us update to the entry. For example, lets change the content and republished:
137
138 published_entry.content = Atom::Content::Html.new("<p>rAtom lets me post to and edit my blog using Ruby, how cool!</p>")
139 published_entry.updated = Time.now
140 published_entry.save!
f2685066 » seangeo 2009-06-18 Doc patch from Wybo Wiersma 141
142 To update an existing Entry:
143
144 existing_entry = Entry.load_entry(URI.parse("http://example.org/afeedentry.atom"))
145
146 existing_entry.title = "I have discovered rAtom"
147 existing_entry.updated = Time.now
148 existing_entry.save!
149
46e74293 » seangeo 2008-03-03 Added content to README. 150 You can also delete an entry using the <tt>destroy!</tt> method, but we won't do that will we?.
151
f0e330a6 » seangeo 2008-04-01 Added documentation for ext... 152 === Extension elements
153
154 As of version 0.3.0, rAtom support simple extension elements on feeds and entries. As defined in the Atom Syndication Format,
155 simple extension elements consist of XML elements from a non-Atom namespace that have no attributes or child elements, i.e.
156 they are empty or only contain text content. These elements are treated as a name value pair where the element namespace
157 and local name make up the key and the content of the element is the value, empty elements will be treated as an empty string.
158
159 To access extension elements use the [] method on the Feed or Entry. For example, if we are parsing the follow Atom document
160 with extensions:
161
162 <?xml version="1.0"?>
163 <feed xmlns="http://www.w3.org/2005/Atom" xmlns:ex="http://example.org">
164 <title>Feed with extensions</title>
165 <ex:myelement>Something important</ex:myelement>
166 </feed>
167
168 We could then access the extension element on the feed using:
169
170 > feed["http://example.org", "myelement"]
171 => ["Something important"]
172
173 Note that the return value is an array. This is because XML allows multiple instances of the element.
174
175 To set an extension element you append to the array:
176
177 > feed['http://example.org', 'myelement'] << 'Something less important'
178 => ["Something important", "Something less important"]
179
180 You can then call to_xml and rAtom will serialize the extension elements into xml.
181
182 > puts feed.to_xml
183 <?xml version="1.0"?>
184 <feed xmlns="http://www.w3.org/2005/Atom">
185 <myelement xmlns="http://example.org">Something important</myelement>
186 <myelement xmlns="http://example.org">Something less important</myelement>
187 </feed>
188
189 Notice that the output repeats the xmlns attribute for each of the extensions, this is semantically the same the input XML, just a bit
190 ugly. It seems to be a limitation of the libxml-Ruby API. But if anyone knows a work around I'd gladly accept a patch (or even advice).
46e74293 » seangeo 2008-03-03 Added content to README. 191
5b0202de » seangeo 2008-07-27 Docs for new custom extensions 192 ==== Custom Extension Classes
193
194 As of version 0.5.0 you can also define your own classes for a extension elements. This is done by first creating an alias
195 for the namespace for the class and then using the +element+ method on the Atom::Feed or Atom::Entry class to tell rAtom
196 to use your custom class when it encounters the extension element.
197
198 For example, say we have the following piece Atom XML with a structured extension element:
199
200 <?xml version='1.0' encoding='UTF-8'?>
201 <entry xmlns='http://www.w3.org/2005/Atom' xmlns:custom='http://custom.namespace'>
202 <id>https://custom.namespace/id/1</id>
203 <link rel='self' type='application/atom+xml' href='https://custom.namespace/id/1'/>
204 <custom:property name='foo' value='bar'/>
205 <custom:property name='baz' value='bat'/>
206 </entry>
207
208 And we want the +custom:property+ elements to be parsed as our own custom class called Custom::Property that is
209 defined like this:
210
211 class Custom::Property
212 attr_accessor :name, :value
213 def initialize(xml)
214 # Custom XML handling
215 end
216 end
217
218 We can tell rAtom about our custom namespace and custom class using the following method calls:
219
220 Atom::Feed..add_extension_namespace :custom, "http://custom.namespace"
221 Atom::Entry.elements "custom:property", :class => Custom::Property
222
223 The first method call registers an alias for the "http://custom.namespace" namespace and the second method call
224 tell rAtom that when it encounters a custom:property element within a Feed it should create an instance of Custom::Property
225 and pass the XML Reader to the constructor of the instance. It is then up to the constructor to populate the objects attributes
3f43294f » seangeo 2008-07-29 Added warning about custom ... 226 from the XML. Note that the alias you create using +add_extension_namespace+ can be anything you want, it doesn't need
227 to match the alias in the actual XML itself.
5b0202de » seangeo 2008-07-27 Docs for new custom extensions 228
229 The custom property will then be available as a method on the rAtom class. In the above example:
230
231 @feed.custom_property.size == 2
232 @feed.custom_property.first.name == 'foo'
233 @feed.custom_property.first.value == 'bar'
234
3f43294f » seangeo 2008-07-29 Added warning about custom ... 235 There is one caveat to this. By using this type of extension support you are permanently modifying the rAtom classes.
236 So if your application process one type of atom extension and you are happy with permanently modified rAtom classes,
237 the extra extensibility might work for you. If on the other hand you process lots of different types of extension you might
238 want to stick with simpler extension mechanism using the [namespace, element] method described above.
239
5b0202de » seangeo 2008-07-27 Docs for new custom extensions 240 (Thanks to nachokb for this feature!!)
241
ba86d5dd » seangeo 2008-06-25 Update docs and add bump to... 242 === Basic Authentication
243
244 All methods that involve HTTP requests now support HTTP Basic Authentication. Authentication credentials are passed
245 as :user and :pass parameters to the methods that invoke the request. For example you can load a feed with HTTP Basic Authentication using:
246
247 Atom::Feed.load_entry(URI.parse("http://example.org/feed.atom"), :user => 'username', :pass => 'password')
248
249 Likewise all the Atom Pub methods support similar parameters, for example you can publish an Entry to a Feed with authentication
250 using:
251
252 feed.publish(entry, :user => 'username', :pass => 'password')
253
254 Or destroy an entry with:
255
256 entry.destroy!(:user => 'username', :pass => 'password')
257
258 rAtom doesn't store these credentials anywhere within the object model so you will need to pass them as arguments to every
259 method call that requires them. This might be a bit of a pain but it does make things simpler and it means that I'm not responsible
260 for protecting your credentials, although if you are using HTTP Basic Authentication there is a good chance your credentials aren't
261 very well protected anyway.
262
9a466e40 » seangeo 2008-08-10 Docs for hmac support 263 === AuthHMAC authentication
264
265 As of version 0.5.1 rAtom also support authentication via HMAC request signing using the AuthHMAC[http://auth-hmac.rubyforge.org] gem. This is made available using the :hmac_access_id and :hmac_secret_key parameters which can be passed to the same methods as the HTTP Basic credentials support.
266
46e74293 » seangeo 2008-03-03 Added content to README. 267 == TODO
268
269 * Support partial content responses from the server.
270 * Support batching of protocol operations.
271 * All my tests have been against internal systems, I'd really like feedback from those who have tried rAtom using existing blog software that supports APP.
804af5d3 » seangeo 2008-03-08 Added some more todo items. 272 * Handle all base uri tests.
273 * Add slug support.
46e74293 » seangeo 2008-03-03 Added content to README. 274
275 == Source Code
276
277 The source repository is accessible via GitHub:
278
279 git clone git://github.com/seangeo/ratom.git
280
281 == Contact Information
282
283 The project page is at http://rubyforge.org/projects/ratom. Please file any bugs or feedback
284 using the trackers and forums there.
285
286 == Authors and Contributors
287
288 rAtom was developed by Peerworks[http://peerworks.org] and written by Sean Geoghegan.
289