ratom 0.4.2 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +5 -0
- data/Manifest.txt +1 -0
- data/README.txt +44 -0
- data/lib/atom/version.rb +2 -2
- data/lib/atom/xml/parser.rb +27 -7
- data/spec/atom_spec.rb +44 -0
- data/spec/fixtures/with_stylesheet.atom +8 -0
- metadata +3 -2
data/History.txt
CHANGED
data/Manifest.txt
CHANGED
@@ -36,6 +36,7 @@ spec/fixtures/created_entry.atom
|
|
36
36
|
spec/fixtures/entry.atom
|
37
37
|
spec/fixtures/multiple_entry.atom
|
38
38
|
spec/fixtures/simple_single_entry.atom
|
39
|
+
spec/fixtures/with_stylesheet.atom
|
39
40
|
spec/paging/first_paged_feed.atom
|
40
41
|
spec/paging/last_paged_feed.atom
|
41
42
|
spec/paging/middle_paged_feed.atom
|
data/README.txt
CHANGED
@@ -181,6 +181,50 @@ You can then call to_xml and rAtom will serialize the extension elements into xm
|
|
181
181
|
Notice that the output repeats the xmlns attribute for each of the extensions, this is semantically the same the input XML, just a bit
|
182
182
|
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).
|
183
183
|
|
184
|
+
==== Custom Extension Classes
|
185
|
+
|
186
|
+
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
|
187
|
+
for the namespace for the class and then using the +element+ method on the Atom::Feed or Atom::Entry class to tell rAtom
|
188
|
+
to use your custom class when it encounters the extension element.
|
189
|
+
|
190
|
+
For example, say we have the following piece Atom XML with a structured extension element:
|
191
|
+
|
192
|
+
<?xml version='1.0' encoding='UTF-8'?>
|
193
|
+
<entry xmlns='http://www.w3.org/2005/Atom' xmlns:custom='http://custom.namespace'>
|
194
|
+
<id>https://custom.namespace/id/1</id>
|
195
|
+
<link rel='self' type='application/atom+xml' href='https://custom.namespace/id/1'/>
|
196
|
+
<custom:property name='foo' value='bar'/>
|
197
|
+
<custom:property name='baz' value='bat'/>
|
198
|
+
</entry>
|
199
|
+
|
200
|
+
And we want the +custom:property+ elements to be parsed as our own custom class called Custom::Property that is
|
201
|
+
defined like this:
|
202
|
+
|
203
|
+
class Custom::Property
|
204
|
+
attr_accessor :name, :value
|
205
|
+
def initialize(xml)
|
206
|
+
# Custom XML handling
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
We can tell rAtom about our custom namespace and custom class using the following method calls:
|
211
|
+
|
212
|
+
Atom::Feed..add_extension_namespace :custom, "http://custom.namespace"
|
213
|
+
Atom::Entry.elements "custom:property", :class => Custom::Property
|
214
|
+
|
215
|
+
The first method call registers an alias for the "http://custom.namespace" namespace and the second method call
|
216
|
+
tell rAtom that when it encounters a custom:property element within a Feed it should create an instance of Custom::Property
|
217
|
+
and pass the XML Reader to the constructor of the instance. It is then up to the constructor to populate the objects attributes
|
218
|
+
from the XML.
|
219
|
+
|
220
|
+
The custom property will then be available as a method on the rAtom class. In the above example:
|
221
|
+
|
222
|
+
@feed.custom_property.size == 2
|
223
|
+
@feed.custom_property.first.name == 'foo'
|
224
|
+
@feed.custom_property.first.value == 'bar'
|
225
|
+
|
226
|
+
(Thanks to nachokb for this feature!!)
|
227
|
+
|
184
228
|
=== Basic Authentication
|
185
229
|
|
186
230
|
All methods that involve HTTP requests now support HTTP Basic Authentication. Authentication credentials are passed
|
data/lib/atom/version.rb
CHANGED
data/lib/atom/xml/parser.rb
CHANGED
@@ -77,7 +77,7 @@ module Atom
|
|
77
77
|
loop do
|
78
78
|
case xml.node_type
|
79
79
|
when XML::Reader::TYPE_ELEMENT
|
80
|
-
if element_specs.include?(xml.local_name) && [Atom::NAMESPACE, Atom::Pub::NAMESPACE].include?(xml.namespace_uri)
|
80
|
+
if element_specs.include?(xml.local_name) && (self.class.known_namespaces + [Atom::NAMESPACE, Atom::Pub::NAMESPACE]).include?(xml.namespace_uri)
|
81
81
|
element_specs[xml.local_name].parse(self, xml)
|
82
82
|
elsif attributes.any?
|
83
83
|
while (xml.move_to_next_attribute == 1)
|
@@ -98,7 +98,9 @@ module Atom
|
|
98
98
|
end
|
99
99
|
|
100
100
|
def next_node_is?(xml, element, ns = nil)
|
101
|
-
|
101
|
+
# Get to the next element
|
102
|
+
while xml.next == 1 && xml.node_type != XML::Reader::TYPE_ELEMENT; end
|
103
|
+
current_node_is?(xml, element, ns)
|
102
104
|
end
|
103
105
|
|
104
106
|
def current_node_is?(xml, element, ns = nil)
|
@@ -114,6 +116,9 @@ module Atom
|
|
114
116
|
def ordered_element_specs; self.class.ordered_element_specs; end
|
115
117
|
def attributes; self.class.attributes; end
|
116
118
|
def o.namespace(ns = @namespace); @namespace = ns; end
|
119
|
+
def o.add_extension_namespace(ns, url); self.extensions_namespaces[ns.to_s] = url; end
|
120
|
+
def o.extensions_namespaces; @extensions_namespaces ||= {} end
|
121
|
+
def o.known_namespaces; @known_namespaces ||= [] end
|
117
122
|
end
|
118
123
|
o.send(:extend, DeclarationMethods)
|
119
124
|
end
|
@@ -138,6 +143,9 @@ module Atom
|
|
138
143
|
namespace_map = NamespaceMap.new(self.class.namespace) if namespace_map.nil?
|
139
144
|
node = XML::Node.new(root_name)
|
140
145
|
node['xmlns'] = self.class.namespace unless nodeonly || !self.class.respond_to?(:namespace)
|
146
|
+
self.class.extensions_namespaces.each do |ns_alias,uri|
|
147
|
+
node["xmlns:#{ns_alias}"] = uri
|
148
|
+
end
|
141
149
|
|
142
150
|
self.class.ordered_element_specs.each do |spec|
|
143
151
|
if spec.single?
|
@@ -210,8 +218,10 @@ module Atom
|
|
210
218
|
options.merge!(names.pop) if names.last.is_a?(Hash)
|
211
219
|
|
212
220
|
names.each do |name|
|
213
|
-
attr_accessor name
|
214
|
-
|
221
|
+
attr_accessor name.to_s.sub(/:/, '_').to_sym
|
222
|
+
ns, local_name = name.to_s[/(.*):(.*)/,1], $2 || name
|
223
|
+
self.known_namespaces << self.extensions_namespaces[ns] if ns
|
224
|
+
self.ordered_element_specs << self.element_specs[local_name.to_s] = ParseSpec.new(name, options)
|
215
225
|
end
|
216
226
|
end
|
217
227
|
|
@@ -220,8 +230,16 @@ module Atom
|
|
220
230
|
options.merge!(names.pop) if names.last.is_a?(Hash)
|
221
231
|
|
222
232
|
names.each do |name|
|
223
|
-
|
224
|
-
|
233
|
+
name_sym = name.to_s.sub(/:/, '_').to_sym
|
234
|
+
attr_writer name_sym
|
235
|
+
define_method name_sym do
|
236
|
+
ivar = :"@#{name_sym}"
|
237
|
+
self.instance_variable_set ivar, [] unless self.instance_variable_defined? ivar
|
238
|
+
self.instance_variable_get ivar
|
239
|
+
end
|
240
|
+
ns, local_name = name.to_s[/(.*):(.*)/,1], $2 || name
|
241
|
+
self.known_namespaces << self.extensions_namespaces[ns] if ns
|
242
|
+
self.ordered_element_specs << self.element_specs[local_name.to_s.singularize] = ParseSpec.new(name, options)
|
225
243
|
end
|
226
244
|
end
|
227
245
|
|
@@ -314,7 +332,9 @@ module Atom
|
|
314
332
|
when :single
|
315
333
|
target.send("#{@attribute}=".to_sym, build(target, xml))
|
316
334
|
when :collection
|
317
|
-
target.send(
|
335
|
+
collection = target.send(@attribute.to_s)
|
336
|
+
element = build(target, xml)
|
337
|
+
collection << element
|
318
338
|
end
|
319
339
|
end
|
320
340
|
|
data/spec/atom_spec.rb
CHANGED
@@ -8,6 +8,7 @@
|
|
8
8
|
require File.dirname(__FILE__) + '/spec_helper.rb'
|
9
9
|
require 'net/http'
|
10
10
|
require 'time'
|
11
|
+
require 'spec/property'
|
11
12
|
|
12
13
|
shared_examples_for 'simple_single_entry.atom attributes' do
|
13
14
|
it "should parse title" do
|
@@ -183,6 +184,12 @@ describe Atom do
|
|
183
184
|
it_should_behave_like "simple_single_entry.atom attributes"
|
184
185
|
end
|
185
186
|
|
187
|
+
describe 'FeedWithStyleSheet' do
|
188
|
+
it "should load without failure" do
|
189
|
+
lambda { feed = Atom::Feed.load_feed(File.open('spec/fixtures/with_stylesheet.atom')) }.should_not raise_error
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
186
193
|
describe 'ComplexFeed' do
|
187
194
|
before(:all) do
|
188
195
|
@feed = Atom::Feed.load_feed(File.open('spec/fixtures/complex_single_entry.atom'))
|
@@ -1045,6 +1052,43 @@ describe Atom do
|
|
1045
1052
|
end
|
1046
1053
|
end
|
1047
1054
|
|
1055
|
+
describe 'custom_extensions' do
|
1056
|
+
before(:all) do
|
1057
|
+
Atom::Entry.add_extension_namespace :ns_alias, "http://custom.namespace"
|
1058
|
+
Atom::Entry.elements "ns_alias:property", :class => Atom::Extensions::Property
|
1059
|
+
@entry = Atom::Entry.load_entry(File.open('spec/fixtures/entry_with_custom_extensions.atom'))
|
1060
|
+
end
|
1061
|
+
|
1062
|
+
it "should_load_custom_extensions_for_entry" do
|
1063
|
+
@entry.ns_alias_property.should_not == []
|
1064
|
+
end
|
1065
|
+
|
1066
|
+
it "should_load_2_custom_extensions_for_entry" do
|
1067
|
+
@entry.ns_alias_property.size.should == 2
|
1068
|
+
end
|
1069
|
+
|
1070
|
+
it "should load correct_data_for_custom_extensions_for_entry" do
|
1071
|
+
@entry.ns_alias_property.map { |x| [x.name, x.value] }.should == [['foo', 'bar'], ['baz', 'bat']]
|
1072
|
+
end
|
1073
|
+
end
|
1074
|
+
|
1075
|
+
describe 'single custom_extensions' do
|
1076
|
+
before(:all) do
|
1077
|
+
Atom::Entry.add_extension_namespace :custom, "http://custom.namespace"
|
1078
|
+
Atom::Entry.element "custom:property", :class => Atom::Extensions::Property
|
1079
|
+
@entry = Atom::Entry.load_entry(File.open('spec/fixtures/entry_with_single_custom_extension.atom'))
|
1080
|
+
end
|
1081
|
+
|
1082
|
+
it "should load single custom extensions for entry" do
|
1083
|
+
@entry.custom_property.should_not be_nil
|
1084
|
+
end
|
1085
|
+
|
1086
|
+
it "should load correct data for custom extensions for entry" do
|
1087
|
+
@entry.custom_property.name.should == 'foo'
|
1088
|
+
@entry.custom_property.value.should == 'bar'
|
1089
|
+
end
|
1090
|
+
end
|
1091
|
+
|
1048
1092
|
describe Atom::Link do
|
1049
1093
|
before(:each) do
|
1050
1094
|
@href = 'http://example.org/next'
|
@@ -0,0 +1,8 @@
|
|
1
|
+
<?xml version='1.0' encoding='UTF-8'?>
|
2
|
+
<?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?>
|
3
|
+
<feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/'>
|
4
|
+
<id>tag:blogger.com,1999:blog-3343849602113720282</id>
|
5
|
+
<updated>2008-07-26T09:01:19.322+01:00</updated>
|
6
|
+
<title type='text'>Blockstack.tv</title>
|
7
|
+
<link rel='alternate' type='text/html' href='http://blockstack.blogspot.com/'/>
|
8
|
+
</feed>
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ratom
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peerworks
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2008-07-
|
13
|
+
date: 2008-07-28 00:00:00 +09:30
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -84,6 +84,7 @@ files:
|
|
84
84
|
- spec/fixtures/entry.atom
|
85
85
|
- spec/fixtures/multiple_entry.atom
|
86
86
|
- spec/fixtures/simple_single_entry.atom
|
87
|
+
- spec/fixtures/with_stylesheet.atom
|
87
88
|
- spec/paging/first_paged_feed.atom
|
88
89
|
- spec/paging/last_paged_feed.atom
|
89
90
|
- spec/paging/middle_paged_feed.atom
|