xommelier 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/.rspec +2 -0
- data/Gemfile +6 -0
- data/README.md +19 -0
- data/Rakefile +20 -0
- data/Termfile +38 -0
- data/console +7 -0
- data/examples/atom.rb +4 -4
- data/lib/xommelier/atom/category.rb +1 -1
- data/lib/xommelier/atom/entry.rb +1 -1
- data/lib/xommelier/atom/generator.rb +1 -1
- data/lib/xommelier/atom/link.rb +1 -1
- data/lib/xommelier/atom/person.rb +1 -1
- data/lib/xommelier/atom/thread.rb +38 -0
- data/lib/xommelier/atom.rb +4 -20
- data/lib/xommelier/core_ext/{integer.rb → numeric.rb} +1 -1
- data/lib/xommelier/core_ext/symbol.rb +9 -0
- data/lib/xommelier/core_ext/uri.rb +11 -5
- data/lib/xommelier/core_ext.rb +2 -1
- data/lib/xommelier/version.rb +1 -1
- data/lib/xommelier/xml/class_methods.rb +1 -0
- data/lib/xommelier/xml/element/serialization.rb +148 -0
- data/lib/xommelier/xml/element/structure.rb +236 -0
- data/lib/xommelier/xml/element.rb +23 -93
- data/lib/xommelier/xml/namespace.rb +0 -1
- data/lib/xommelier/xml.rb +1 -2
- data/spec/fixtures/feed.atom +39 -0
- data/spec/fixtures/simple_feed.atom +17 -0
- data/spec/lib/xommelier/atom/entry_spec.rb +18 -0
- data/spec/lib/xommelier/xml/element/serialization_spec.rb +36 -0
- data/spec/lib/xommelier/xml/element/structure_spec.rb +27 -0
- data/spec/lib/xommelier/xml/element_spec.rb +21 -38
- data/spec/lib/xommelier/xml_spec.rb +2 -4
- data/spec/lib/xommelier_spec.rb +1 -1
- data/spec/namespaced_module.rb +0 -3
- data/spec/spec_helper.rb +5 -3
- data/xommelier.gemspec +2 -2
- metadata +62 -49
- data/lib/xommelier/xml/attribute.rb +0 -8
- data/lib/xommelier/xml/element/dsl.rb +0 -51
@@ -0,0 +1,236 @@
|
|
1
|
+
require 'xommelier/xml/element'
|
2
|
+
require 'active_support/core_ext/module/delegation'
|
3
|
+
require 'active_support/core_ext/object/with_options'
|
4
|
+
require 'active_support/core_ext/string/inflections'
|
5
|
+
require 'active_support/inflections'
|
6
|
+
|
7
|
+
module Xommelier
|
8
|
+
module Xml
|
9
|
+
class Element
|
10
|
+
module Structure
|
11
|
+
extend ActiveSupport::Concern
|
12
|
+
|
13
|
+
included do
|
14
|
+
class_attribute :elements, :attributes
|
15
|
+
attr_writer :element_name
|
16
|
+
|
17
|
+
self.elements = {}
|
18
|
+
self.attributes = {}
|
19
|
+
|
20
|
+
class << self
|
21
|
+
include SingletonClassMethods
|
22
|
+
end
|
23
|
+
|
24
|
+
delegate :xmlns, to: 'self.class'
|
25
|
+
end
|
26
|
+
|
27
|
+
module SingletonClassMethods
|
28
|
+
def containing_module
|
29
|
+
@containing_module ||= ("::#{name.gsub(/::[^:]+$/, '')}").constantize
|
30
|
+
end
|
31
|
+
|
32
|
+
def xmlns(value = nil)
|
33
|
+
if value
|
34
|
+
@xmlns = case value
|
35
|
+
when Module
|
36
|
+
value.xmlns
|
37
|
+
else
|
38
|
+
value
|
39
|
+
end
|
40
|
+
end
|
41
|
+
@xmlns ||= find_namespace
|
42
|
+
end
|
43
|
+
alias_method :xmlns=, :xmlns
|
44
|
+
|
45
|
+
def element_name(element_name = nil)
|
46
|
+
@element_name = element_name if element_name
|
47
|
+
@element_name ||= find_element_name
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def find_namespace
|
53
|
+
if self == containing_module
|
54
|
+
Xommelier::Xml::DEFAULT_NS
|
55
|
+
else
|
56
|
+
containing_module.xmlns
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def find_element_name
|
61
|
+
name.demodulize.underscore.dasherize
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
module ClassMethods
|
66
|
+
def inherited(child)
|
67
|
+
child.elements = elements.dup
|
68
|
+
child.attributes = attributes.dup
|
69
|
+
end
|
70
|
+
|
71
|
+
# Defines containing element
|
72
|
+
# @example
|
73
|
+
# element :author, class_name: 'Xommelier::Atom::Person'
|
74
|
+
def element(name, options = {})
|
75
|
+
options[:element_name] = name
|
76
|
+
elements[name] = DEFAULT_ELEMENT_OPTIONS.merge(options)
|
77
|
+
define_element_accessors(name)
|
78
|
+
end
|
79
|
+
|
80
|
+
# Defines containing attribute
|
81
|
+
def attribute(name, options = {})
|
82
|
+
attributes[name] = DEFAULT_OPTIONS.merge(options)
|
83
|
+
define_attribute_accessors(name)
|
84
|
+
end
|
85
|
+
|
86
|
+
# Defines containing text
|
87
|
+
def text(options = {})
|
88
|
+
define_text_accessors
|
89
|
+
end
|
90
|
+
|
91
|
+
def any(&block)
|
92
|
+
with_options(count: :any) { |any| any.instance_eval(&block) }
|
93
|
+
end
|
94
|
+
|
95
|
+
def many(&block)
|
96
|
+
with_options(count: :many) { |many| many.instance_eval(&block) }
|
97
|
+
end
|
98
|
+
|
99
|
+
def may(&block)
|
100
|
+
with_options(count: :may) { |may| may.instance_eval(&block) }
|
101
|
+
end
|
102
|
+
|
103
|
+
def root; end
|
104
|
+
|
105
|
+
private
|
106
|
+
|
107
|
+
def define_element_accessors(name)
|
108
|
+
element_options = elements[name]
|
109
|
+
case element_options[:count]
|
110
|
+
when :one, :may
|
111
|
+
name = name.to_sym
|
112
|
+
define_method(name) do |*args|
|
113
|
+
if args[0]
|
114
|
+
write_element(name, args[0])
|
115
|
+
end
|
116
|
+
read_element(name)
|
117
|
+
end
|
118
|
+
alias_method "#{name}=", name
|
119
|
+
when :many, :any
|
120
|
+
plural = name.to_s.pluralize.to_sym
|
121
|
+
element_options[:plural] = plural
|
122
|
+
|
123
|
+
define_method(plural) do |*args|
|
124
|
+
if args.any?
|
125
|
+
@elements[name] = args.flatten
|
126
|
+
end
|
127
|
+
@elements[name] ||= []
|
128
|
+
end
|
129
|
+
alias_method "#{plural}=", plural
|
130
|
+
|
131
|
+
unless plural == name
|
132
|
+
define_method(name) do |*args|
|
133
|
+
if args[0]
|
134
|
+
send(plural, [args[0]])
|
135
|
+
else
|
136
|
+
send(plural)[0]
|
137
|
+
end
|
138
|
+
end
|
139
|
+
alias_method "#{name}=", name
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
protected
|
145
|
+
|
146
|
+
def define_attribute_accessors(name)
|
147
|
+
define_method(name) do |*args|
|
148
|
+
if args[0]
|
149
|
+
write_attribute(name.to_s, args[0])
|
150
|
+
end
|
151
|
+
read_attribute(name)
|
152
|
+
end
|
153
|
+
alias_method "#{name}=", name
|
154
|
+
end
|
155
|
+
|
156
|
+
def define_text_accessors
|
157
|
+
define_method(:text) do |*args|
|
158
|
+
if args[0]
|
159
|
+
write_text(args[0])
|
160
|
+
end
|
161
|
+
read_text
|
162
|
+
end
|
163
|
+
alias_method :text=, :text
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
protected
|
168
|
+
|
169
|
+
def element_name(value = nil)
|
170
|
+
if value
|
171
|
+
@element_name = value
|
172
|
+
end
|
173
|
+
@element_name ||= self.class.element_name
|
174
|
+
end
|
175
|
+
|
176
|
+
def element_options(name)
|
177
|
+
self.class.elements[name.to_sym]
|
178
|
+
end
|
179
|
+
|
180
|
+
def read_element(name)
|
181
|
+
@elements[name.to_sym]
|
182
|
+
end
|
183
|
+
|
184
|
+
def write_element(name, value)
|
185
|
+
type = element_options(name)[:type]
|
186
|
+
unless value.is_a?(type)
|
187
|
+
value = if (type < Xommelier::Xml::Element) && !value.is_a?(Nokogiri::XML::Node)
|
188
|
+
type.new(value)
|
189
|
+
else
|
190
|
+
type.from_xommelier(value)
|
191
|
+
end
|
192
|
+
end
|
193
|
+
@elements[name.to_sym] = value
|
194
|
+
end
|
195
|
+
|
196
|
+
def remove_element(name)
|
197
|
+
@elements.delete(name.to_sym)
|
198
|
+
end
|
199
|
+
|
200
|
+
def attribute_options(name)
|
201
|
+
self.class.attributes[name.to_sym]
|
202
|
+
end
|
203
|
+
|
204
|
+
def read_attribute(name)
|
205
|
+
@attributes[name.to_sym]
|
206
|
+
end
|
207
|
+
|
208
|
+
def write_attribute(name, value)
|
209
|
+
type = attribute_options(name)[:type]
|
210
|
+
value = type.from_xommelier(value) unless value.is_a?(type)
|
211
|
+
@attributes[name.to_sym] = value
|
212
|
+
end
|
213
|
+
|
214
|
+
def remove_attribute(name)
|
215
|
+
@attributes.delete(name.to_sym)
|
216
|
+
end
|
217
|
+
|
218
|
+
def text?
|
219
|
+
respond_to?(:text)
|
220
|
+
end
|
221
|
+
|
222
|
+
def read_text
|
223
|
+
@text
|
224
|
+
end
|
225
|
+
|
226
|
+
def write_text(text)
|
227
|
+
@text = text
|
228
|
+
end
|
229
|
+
|
230
|
+
def remove_text
|
231
|
+
@text = nil
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'xommelier/xml'
|
2
|
-
require 'xommelier/xml/element/
|
3
|
-
require '
|
2
|
+
require 'xommelier/xml/element/structure'
|
3
|
+
require 'xommelier/xml/element/serialization'
|
4
4
|
require 'active_support/core_ext/string/inflections'
|
5
5
|
require 'active_support/core_ext/array/extract_options'
|
6
6
|
require 'active_support/core_ext/class/attribute'
|
@@ -15,48 +15,13 @@ module Xommelier
|
|
15
15
|
)
|
16
16
|
|
17
17
|
class Element
|
18
|
-
|
18
|
+
include Xommelier::Xml::Element::Structure
|
19
|
+
include Xommelier::Xml::Element::Serialization
|
19
20
|
|
20
|
-
|
21
|
-
self.elements = {}
|
22
|
-
self.attributes = {}
|
23
|
-
|
24
|
-
class << self
|
25
|
-
def xmlns(value = nil)
|
26
|
-
if value
|
27
|
-
@xmlns = case ns
|
28
|
-
when Module
|
29
|
-
ns.xmlns
|
30
|
-
else
|
31
|
-
ns
|
32
|
-
end
|
33
|
-
end
|
34
|
-
@xmlns ||= find_namespace
|
35
|
-
end
|
36
|
-
alias xmlns= xmlns
|
37
|
-
|
38
|
-
def element_name(element_name = nil)
|
39
|
-
@element_name = element_name if element_name
|
40
|
-
@element_name ||= find_element_name
|
41
|
-
end
|
42
|
-
|
43
|
-
private
|
44
|
-
|
45
|
-
def containing_module
|
46
|
-
@containing_module ||= ("::#{name.gsub(/::[^:]+$/, '')}").constantize
|
47
|
-
end
|
48
|
-
|
49
|
-
def find_namespace
|
50
|
-
containing_module.xmlns
|
51
|
-
end
|
52
|
-
|
53
|
-
def find_element_name
|
54
|
-
name.demodulize.tableize.dasherize
|
55
|
-
end
|
56
|
-
end
|
21
|
+
attr_reader :options
|
57
22
|
|
58
23
|
def initialize(contents = {}, options = {})
|
59
|
-
|
24
|
+
self.options = options
|
60
25
|
|
61
26
|
@elements = {}
|
62
27
|
@attributes = {}
|
@@ -72,70 +37,35 @@ module Xommelier
|
|
72
37
|
end
|
73
38
|
end
|
74
39
|
|
75
|
-
def
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
builder = Nokogiri::XML::Builder.new(options)
|
82
|
-
attribute_values = {xmlns: xmlns.to_s}
|
83
|
-
end
|
84
|
-
attributes.each do |name, value|
|
85
|
-
serialize_attribute(name, value, attribute_values)
|
86
|
-
end
|
87
|
-
builder.send(element_name, attribute_values) do |xml|
|
88
|
-
if respond_to?(:text)
|
89
|
-
xml.text @text
|
90
|
-
else
|
91
|
-
elements.each do |name, value|
|
92
|
-
serialize_element(name, value, xml)
|
93
|
-
end
|
94
|
-
end
|
40
|
+
def options=(options = {})
|
41
|
+
@options = options
|
42
|
+
@options.delete(:type)
|
43
|
+
|
44
|
+
if @options.key?(:element_name)
|
45
|
+
element_name(@options.delete(:element_name))
|
95
46
|
end
|
96
|
-
builder.to_xml
|
97
47
|
end
|
98
48
|
|
99
|
-
|
100
|
-
|
101
|
-
def element_options(name)
|
102
|
-
self.class.elements[name]
|
49
|
+
def inspect
|
50
|
+
%(#<#{self.class.name}:0x#{object_id.to_s(16)} #{inspect_contents}>)
|
103
51
|
end
|
104
52
|
|
105
|
-
|
106
|
-
self.class.attributes[name]
|
107
|
-
end
|
53
|
+
private
|
108
54
|
|
109
|
-
def
|
110
|
-
|
55
|
+
def inspect_contents
|
56
|
+
[inspect_attributes, inspect_elements, inspect_text].compact.join(' ')
|
111
57
|
end
|
112
58
|
|
113
|
-
def
|
114
|
-
|
59
|
+
def inspect_attributes
|
60
|
+
"@attributes={#{@attributes.map { |name, value| "#{name}: #{value.inspect}"}.join(', ')}}" if @attributes.any?
|
115
61
|
end
|
116
62
|
|
117
|
-
def
|
118
|
-
|
119
|
-
attribute_class = attribute_options[:type]
|
120
|
-
value = attribute_class.new(value) unless value.is_a?(attribute_class)
|
121
|
-
attributes[name] = value.to_xommelier
|
63
|
+
def inspect_elements
|
64
|
+
"#{@elements.map { |name, value| "@#{name}=#{value.inspect}"}.join(' ')}" if @elements.any?
|
122
65
|
end
|
123
66
|
|
124
|
-
def
|
125
|
-
|
126
|
-
if element_options[:count] == :many
|
127
|
-
single_element = element_options.merge(count: :one)
|
128
|
-
value.each { |item| serialize_element(name, item, xml, single_element) }
|
129
|
-
else
|
130
|
-
element_class = element_options[:type]
|
131
|
-
value = element_class.new(value) unless value.is_a?(element_class)
|
132
|
-
case value
|
133
|
-
when Xommelier::Xml::Element
|
134
|
-
value.to_xml(builder: xml, element_name: name)
|
135
|
-
else
|
136
|
-
xml.send(name) { xml.text value.to_xommelier }
|
137
|
-
end
|
138
|
-
end
|
67
|
+
def inspect_text
|
68
|
+
text.inspect if text?
|
139
69
|
end
|
140
70
|
end
|
141
71
|
end
|
@@ -17,7 +17,6 @@ module Xommelier
|
|
17
17
|
@uri = uri
|
18
18
|
@options = {}
|
19
19
|
@elements = Xommelier::Collection.new(Xommelier::Xml::Element)
|
20
|
-
@attributes = Xommelier::Collection.new(Xommelier::Xml::Attribute)
|
21
20
|
@as = options.delete(:as)
|
22
21
|
|
23
22
|
Xommelier::Xml::Namespace.registry[as] = self
|
data/lib/xommelier/xml.rb
CHANGED
@@ -6,7 +6,7 @@ module Xommelier
|
|
6
6
|
module Xml
|
7
7
|
extend ActiveSupport::Concern
|
8
8
|
|
9
|
-
|
9
|
+
DEFAULT_NS = 'http://www.w3.org/XML/1998/namespace'
|
10
10
|
|
11
11
|
included do
|
12
12
|
instance_variable_set :@_xmlns, nil
|
@@ -14,6 +14,5 @@ module Xommelier
|
|
14
14
|
|
15
15
|
autoload :Namespace, 'xommelier/xml/namespace'
|
16
16
|
autoload :Element, 'xommelier/xml/element'
|
17
|
-
autoload :Attribute, 'xommelier/xml/attribute'
|
18
17
|
end
|
19
18
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
<feed xmlns="http://www.w3.org/2005/Atom">
|
3
|
+
<id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
|
4
|
+
<title type="text">Example Feed</title>
|
5
|
+
<updated>2003-12-13T18:30:02Z</updated>
|
6
|
+
<subtitle type="html">A <em>lot</em> of effort went into making this effortless</subtitle>
|
7
|
+
<link rel="alternate" type="text/html" href="http://example.ru/" />
|
8
|
+
<link rel="self" type="application/atom+xml" href="http://example.ru/feed.atom" />
|
9
|
+
<rights>© Mark Pilgrim, 2003</rights>
|
10
|
+
<generator uri="http://example.com/" version="1.0">Example Toolkit</generator>
|
11
|
+
<author>
|
12
|
+
<name>John Doe</name>
|
13
|
+
</author>
|
14
|
+
<entry>
|
15
|
+
<id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
|
16
|
+
<title type="text">Atom-Powered Robots Run Amok</title>
|
17
|
+
<updated>2003-12-13T18:30:02Z</updated>
|
18
|
+
<published>2003-12-13T08:29:29-04:00</published>
|
19
|
+
<link rel="alternate" type="text/html" href="http://example.ru/2003/12/13/atom03"/>
|
20
|
+
<link rel="enclosure" type="audio/mpeg" href="http://example.org/audio/ph34r_my_podcast.mp3" length="1337"/>
|
21
|
+
<author>
|
22
|
+
<name>Mark Pilgrim</name>
|
23
|
+
<uri>http://example.org/</uri>
|
24
|
+
<email>f8dy@example.com</email>
|
25
|
+
</author>
|
26
|
+
<contributor>
|
27
|
+
<name>Sam Ruby</name>
|
28
|
+
</contributor>
|
29
|
+
<contributor>
|
30
|
+
<name>Joe Gregorio</name>
|
31
|
+
</contributor>
|
32
|
+
<summary>Some text.</summary>
|
33
|
+
<content type="xhtml" xml:lang="en" xml:base="http://diveintomark.org/">
|
34
|
+
<div xmlns="http://www.w3.org/1999/xhtml">
|
35
|
+
<p><i>[Update: The Atom draft is finished.]</i></p>
|
36
|
+
</div>
|
37
|
+
</content>
|
38
|
+
</entry>
|
39
|
+
</feed>
|
@@ -0,0 +1,17 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
<feed xmlns="http://www.w3.org/2005/Atom">
|
3
|
+
<id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
|
4
|
+
<title>Example Feed</title>
|
5
|
+
<link href="http://example.org/"/>
|
6
|
+
<updated>2003-12-13T18:30:02Z</updated>
|
7
|
+
<author>
|
8
|
+
<name>John Doe</name>
|
9
|
+
</author>
|
10
|
+
<entry>
|
11
|
+
<title>Atom-Powered Robots Run Amok</title>
|
12
|
+
<link href="http://example.org/2003/12/13/atom03"/>
|
13
|
+
<id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
|
14
|
+
<updated>2003-12-13T18:30:02Z</updated>
|
15
|
+
<summary>Some text.</summary>
|
16
|
+
</entry>
|
17
|
+
</feed>
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Xommelier::Atom::Entry do
|
4
|
+
describe 'instance' do
|
5
|
+
subject { Xommelier::Atom::Entry.new }
|
6
|
+
|
7
|
+
[:id, :title, :updated].each do |must_field|
|
8
|
+
it { should respond_to(must_field) }
|
9
|
+
end
|
10
|
+
[:content, :published, :rights, :source, :summary].each do |may_field|
|
11
|
+
it { should respond_to(may_field) }
|
12
|
+
end
|
13
|
+
%w(author category contributor link).each do |any_field|
|
14
|
+
it { should respond_to(any_field) }
|
15
|
+
it('have plural methods for embedded collections') { should respond_to(any_field.pluralize) }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Xommelier::Xml::Element::Serialization do
|
4
|
+
describe 'class' do
|
5
|
+
subject { Xommelier::Atom::Feed }
|
6
|
+
|
7
|
+
it { should respond_to(:parse) }
|
8
|
+
end
|
9
|
+
|
10
|
+
describe 'parsing simple_feed' do
|
11
|
+
let(:feed) { @feed = Xommelier::Atom::Feed.parse(open(File.join(SPEC_ROOT, 'spec', 'fixtures', 'simple_feed.atom'))) }
|
12
|
+
|
13
|
+
it { feed.id.should == 'urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6' }
|
14
|
+
it { feed.title.should == 'Example Feed' }
|
15
|
+
it { feed.link.href.should == URI.parse('http://example.org/') }
|
16
|
+
it { feed.updated.should == Time.utc(2003, 12, 13, 18, 30, 02) }
|
17
|
+
it { feed.should have(1).authors }
|
18
|
+
it { feed.author.name.should == 'John Doe' }
|
19
|
+
it { feed.should have(1).entries }
|
20
|
+
it { feed.entry.title.should == 'Atom-Powered Robots Run Amok' }
|
21
|
+
it { feed.entry.link.href.should == URI.parse('http://example.org/2003/12/13/atom03') }
|
22
|
+
it { feed.entry.id.should == 'urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a' }
|
23
|
+
it { feed.entry.updated.should == Time.utc(2003, 12, 13, 18, 30, 02) }
|
24
|
+
it { feed.entry.summary.should == 'Some text.' }
|
25
|
+
end
|
26
|
+
|
27
|
+
describe 'parsing feed' do
|
28
|
+
let(:feed) { Xommelier::Atom::Feed.parse(open(File.join(SPEC_ROOT, 'spec', 'fixtures', 'feed.atom'))) }
|
29
|
+
|
30
|
+
it { feed.should have(2).links }
|
31
|
+
it { feed.subtitle.should == 'A <em>lot</em> of effort went into making this effortless' }
|
32
|
+
it { feed.entry.should have(2).links }
|
33
|
+
it { feed.entry.should have(1).authors }
|
34
|
+
it { feed.entry.should have(2).contributors }
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Xommelier::Xml::Element::Structure do
|
4
|
+
subject { NamespacedModule::RootWithSimpleSubelement }
|
5
|
+
|
6
|
+
it { should respond_to(:elements) }
|
7
|
+
it { should respond_to(:element) }
|
8
|
+
it 'defines subelement' do
|
9
|
+
NamespacedModule::RootWithSimpleSubelement.elements.should have_key(:some)
|
10
|
+
end
|
11
|
+
|
12
|
+
it { should respond_to(:attributes) }
|
13
|
+
it { should respond_to(:attribute) }
|
14
|
+
it 'defines attribute' do
|
15
|
+
NamespacedModule::RootWithAttribute.attributes.should have_key(:another)
|
16
|
+
end
|
17
|
+
|
18
|
+
it { should respond_to(:text) }
|
19
|
+
it 'defines as containing text' do
|
20
|
+
NamespacedModule::RootWithText.new.should respond_to(:text)
|
21
|
+
end
|
22
|
+
|
23
|
+
it { should respond_to(:xmlns) }
|
24
|
+
it { NamespacedModule::RootWithText.xmlns.uri.should == 'http://example.org/'}
|
25
|
+
it { NamespacedModule::RootWithAttribute.xmlns.uri.should == 'http://example.org/'}
|
26
|
+
it { Xommelier::Atom::Feed.xmlns.uri.should == 'http://www.w3.org/2005/Atom'}
|
27
|
+
end
|
@@ -2,67 +2,46 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Xommelier::Xml::Element do
|
4
4
|
describe 'class' do
|
5
|
-
subject {
|
5
|
+
subject { Xommelier::Atom::Link }
|
6
6
|
|
7
7
|
it { should respond_to(:xmlns) }
|
8
|
-
it { subject.xmlns.to_s.should ==
|
8
|
+
it { subject.xmlns.to_s.should == ATOM_XMLNS }
|
9
9
|
|
10
10
|
it { should respond_to(:element_name) }
|
11
|
-
it { subject.element_name.should == '
|
12
|
-
|
13
|
-
it { should respond_to(:elements) }
|
14
|
-
it { should respond_to(:attributes) }
|
15
|
-
end
|
16
|
-
|
17
|
-
describe 'DSL' do
|
18
|
-
subject { NamespacedModule::RootWithSimpleSubelement }
|
19
|
-
|
20
|
-
it { should respond_to(:element) }
|
21
|
-
it 'defines subelement' do
|
22
|
-
NamespacedModule::RootWithSimpleSubelement.elements.should have_key(:some)
|
23
|
-
end
|
24
|
-
|
25
|
-
it { should respond_to(:attribute) }
|
26
|
-
it 'defines attribute' do
|
27
|
-
NamespacedModule::RootWithAttribute.attributes.should have_key(:another)
|
28
|
-
end
|
29
|
-
|
30
|
-
it { should respond_to(:text) }
|
31
|
-
it 'defines as containing text' do
|
32
|
-
NamespacedModule::RootWithText.new.should respond_to(:text)
|
33
|
-
end
|
11
|
+
it { subject.element_name.should == 'link' }
|
34
12
|
end
|
35
13
|
|
36
14
|
describe 'instance' do
|
37
|
-
subject {
|
15
|
+
subject { Xommelier::Atom::Link.new }
|
38
16
|
|
39
17
|
it { should respond_to(:to_xml) }
|
40
|
-
it { subject.to_xml.should == %(<?xml version="1.0"?>\n<
|
18
|
+
it { subject.to_xml.should == %(<?xml version="1.0" encoding="utf-8"?>\n<link xmlns="#{ATOM_XMLNS}"/>\n) }
|
41
19
|
|
42
20
|
describe 'with text' do
|
43
21
|
subject { NamespacedModule::RootWithText.new('Text') }
|
44
22
|
|
45
23
|
it { should respond_to(:text) }
|
46
24
|
it { subject.text.should == 'Text' }
|
47
|
-
it { subject.to_xml.should == %(<?xml version="1.0"?>\n<root-with-text xmlns="http://example.org/">Text</root-with-text>\n) }
|
25
|
+
it { subject.to_xml.should == %(<?xml version="1.0" encoding="utf-8"?>\n<root-with-text xmlns="http://example.org/">Text</root-with-text>\n) }
|
48
26
|
end
|
49
27
|
|
50
28
|
describe 'with simple subelements' do
|
51
|
-
subject {
|
29
|
+
subject { Xommelier::Atom::Person.new(name: 'Ivan') }
|
52
30
|
|
53
|
-
it { should respond_to(:
|
54
|
-
it { subject.
|
55
|
-
it { subject.to_xml.should == %(<?xml version="1.0"?>\n<
|
31
|
+
it { should respond_to(:name) }
|
32
|
+
it { subject.name.should == 'Ivan' }
|
33
|
+
it { subject.to_xml.should == %(<?xml version="1.0" encoding="utf-8"?>\n<person xmlns="#{ATOM_XMLNS}">\n <name>Ivan</name>\n</person>\n) }
|
56
34
|
end
|
57
35
|
|
58
36
|
describe 'with many simple subelements' do
|
59
37
|
subject do
|
60
|
-
NamespacedModule::RootWithManySimpleSubelements.new(
|
38
|
+
NamespacedModule::RootWithManySimpleSubelements.new(foos: ['bar', 'baz'])
|
61
39
|
end
|
62
40
|
|
63
41
|
it { should respond_to(:foo) }
|
64
|
-
it { subject.
|
65
|
-
it { subject.
|
42
|
+
it { subject.foos.should == ['bar', 'baz'] }
|
43
|
+
it { subject.foo.should == 'bar' }
|
44
|
+
it { subject.to_xml.should == %(<?xml version="1.0" encoding="utf-8"?>\n<root-with-many-simple-subelements xmlns="http://example.org/">\n <foo>bar</foo>\n <foo>baz</foo>\n</root-with-many-simple-subelements>\n) }
|
66
45
|
end
|
67
46
|
|
68
47
|
describe 'with attribute' do
|
@@ -70,7 +49,7 @@ describe Xommelier::Xml::Element do
|
|
70
49
|
|
71
50
|
it { should respond_to(:another) }
|
72
51
|
it { subject.another.should == 'Difference' }
|
73
|
-
it { subject.to_xml.should == %(<?xml version="1.0"?>\n<root-with-attribute xmlns="http://example.org/" another="Difference"/>\n) }
|
52
|
+
it { subject.to_xml.should == %(<?xml version="1.0" encoding="utf-8"?>\n<root-with-attribute xmlns="http://example.org/" another="Difference"/>\n) }
|
74
53
|
end
|
75
54
|
|
76
55
|
describe 'with subelements' do
|
@@ -84,8 +63,12 @@ describe Xommelier::Xml::Element do
|
|
84
63
|
end
|
85
64
|
|
86
65
|
it { should respond_to(:one) }
|
87
|
-
it {
|
88
|
-
it {
|
66
|
+
it { should respond_to(:two) }
|
67
|
+
it { should respond_to(:some) }
|
68
|
+
it { should respond_to(:another) }
|
69
|
+
it { subject.another.class.should == NamespacedModule::RootWithSimpleSubelement }
|
70
|
+
it { subject.another.some.should == 'Text' }
|
71
|
+
it { subject.to_xml.should == %(<?xml version="1.0" encoding="utf-8"?>\n<root-with-subelement xmlns="http://example.org/" one="2011-08-15" two="2">\n <some>Text</some>\n <another>\n <some>Text</some>\n </another>\n</root-with-subelement>\n) }
|
89
72
|
end
|
90
73
|
end
|
91
74
|
end
|
@@ -3,9 +3,7 @@ require 'spec_helper'
|
|
3
3
|
describe Xommelier::Xml do
|
4
4
|
end
|
5
5
|
|
6
|
-
describe
|
7
|
-
subject { NamespacedModule }
|
8
|
-
|
6
|
+
describe Xommelier::Atom do
|
9
7
|
it { should respond_to(:xmlns) }
|
10
|
-
it { subject.xmlns.to_s.should ==
|
8
|
+
it { subject.xmlns.to_s.should == ATOM_XMLNS }
|
11
9
|
end
|
data/spec/lib/xommelier_spec.rb
CHANGED