doxo-roxml 2.5.3
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +279 -0
- data/MIT-LICENSE +18 -0
- data/Manifest.txt +103 -0
- data/README.rdoc +158 -0
- data/Rakefile +96 -0
- data/TODO +62 -0
- data/config/website.yml +2 -0
- data/examples/active_record.rb +70 -0
- data/examples/amazon.rb +33 -0
- data/examples/current_weather.rb +27 -0
- data/examples/dashed_elements.rb +20 -0
- data/examples/library.rb +40 -0
- data/examples/posts.rb +27 -0
- data/examples/twitter.rb +37 -0
- data/examples/xml/active_record.xml +70 -0
- data/examples/xml/amazon.xml +133 -0
- data/examples/xml/current_weather.xml +89 -0
- data/examples/xml/dashed_elements.xml +52 -0
- data/examples/xml/posts.xml +23 -0
- data/examples/xml/twitter.xml +422 -0
- data/lib/roxml.rb +511 -0
- data/lib/roxml/definition.rb +234 -0
- data/lib/roxml/extensions.rb +6 -0
- data/lib/roxml/extensions/array.rb +13 -0
- data/lib/roxml/extensions/array/conversions.rb +12 -0
- data/lib/roxml/extensions/deprecation.rb +33 -0
- data/lib/roxml/extensions/string.rb +6 -0
- data/lib/roxml/extensions/string/conversions.rb +5 -0
- data/lib/roxml/extensions/string/iterators.rb +12 -0
- data/lib/roxml/hash_definition.rb +25 -0
- data/lib/roxml/xml.rb +40 -0
- data/lib/roxml/xml/parsers/libxml.rb +86 -0
- data/lib/roxml/xml/parsers/rexml.rb +84 -0
- data/lib/roxml/xml/references.rb +299 -0
- data/roxml.gemspec +50 -0
- data/spec/definition_spec.rb +490 -0
- data/spec/examples/active_record_spec.rb +40 -0
- data/spec/examples/amazon_spec.rb +53 -0
- data/spec/examples/current_weather_spec.rb +37 -0
- data/spec/examples/dashed_elements_spec.rb +20 -0
- data/spec/examples/library_spec.rb +46 -0
- data/spec/examples/post_spec.rb +24 -0
- data/spec/examples/twitter_spec.rb +32 -0
- data/spec/roxml_spec.rb +372 -0
- data/spec/shared_specs.rb +15 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +33 -0
- data/spec/xml/parser_spec.rb +47 -0
- data/tasks/rspec.rake +21 -0
- data/tasks/test.rake +42 -0
- data/test/bugs/rexml_bugs.rb +15 -0
- data/test/fixtures/book_malformed.xml +5 -0
- data/test/fixtures/book_pair.xml +8 -0
- data/test/fixtures/book_text_with_attribute.xml +5 -0
- data/test/fixtures/book_valid.xml +5 -0
- data/test/fixtures/book_with_authors.xml +7 -0
- data/test/fixtures/book_with_contributions.xml +9 -0
- data/test/fixtures/book_with_contributors.xml +7 -0
- data/test/fixtures/book_with_contributors_attrs.xml +7 -0
- data/test/fixtures/book_with_default_namespace.xml +9 -0
- data/test/fixtures/book_with_depth.xml +6 -0
- data/test/fixtures/book_with_octal_pages.xml +4 -0
- data/test/fixtures/book_with_publisher.xml +7 -0
- data/test/fixtures/book_with_wrapped_attr.xml +3 -0
- data/test/fixtures/dictionary_of_attr_name_clashes.xml +8 -0
- data/test/fixtures/dictionary_of_attrs.xml +6 -0
- data/test/fixtures/dictionary_of_guarded_names.xml +6 -0
- data/test/fixtures/dictionary_of_mixeds.xml +4 -0
- data/test/fixtures/dictionary_of_name_clashes.xml +10 -0
- data/test/fixtures/dictionary_of_names.xml +4 -0
- data/test/fixtures/dictionary_of_texts.xml +10 -0
- data/test/fixtures/library.xml +30 -0
- data/test/fixtures/library_uppercase.xml +30 -0
- data/test/fixtures/muffins.xml +3 -0
- data/test/fixtures/nameless_ageless_youth.xml +2 -0
- data/test/fixtures/node_with_attr_name_conflicts.xml +1 -0
- data/test/fixtures/node_with_name_conflicts.xml +4 -0
- data/test/fixtures/numerology.xml +4 -0
- data/test/fixtures/person.xml +1 -0
- data/test/fixtures/person_with_guarded_mothers.xml +13 -0
- data/test/fixtures/person_with_mothers.xml +10 -0
- data/test/mocks/dictionaries.rb +57 -0
- data/test/mocks/mocks.rb +279 -0
- data/test/test_helper.rb +45 -0
- data/test/unit/definition_test.rb +235 -0
- data/test/unit/deprecations_test.rb +24 -0
- data/test/unit/to_xml_test.rb +81 -0
- data/test/unit/xml_attribute_test.rb +39 -0
- data/test/unit/xml_block_test.rb +81 -0
- data/test/unit/xml_bool_test.rb +122 -0
- data/test/unit/xml_convention_test.rb +150 -0
- data/test/unit/xml_hash_test.rb +115 -0
- data/test/unit/xml_initialize_test.rb +49 -0
- data/test/unit/xml_name_test.rb +141 -0
- data/test/unit/xml_namespace_test.rb +76 -0
- data/test/unit/xml_object_test.rb +207 -0
- data/test/unit/xml_required_test.rb +93 -0
- data/test/unit/xml_text_test.rb +71 -0
- data/vendor/override_rake_task/README +30 -0
- data/vendor/override_rake_task/init.rb +1 -0
- data/vendor/override_rake_task/install.rb +46 -0
- data/vendor/override_rake_task/lib/override_rake_task.rb +16 -0
- data/website/index.html +98 -0
- metadata +234 -0
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'rexml/document'
|
2
|
+
|
3
|
+
module ROXML
|
4
|
+
module XML # :nodoc:all
|
5
|
+
Document = REXML::Document
|
6
|
+
Node = REXML::Element
|
7
|
+
|
8
|
+
module Error
|
9
|
+
def self.reset_handler
|
10
|
+
# noop
|
11
|
+
end
|
12
|
+
end
|
13
|
+
[REXML::ParseException, REXML::UndefinedNamespaceException, REXML::Validation::ValidationException].each do |exception|
|
14
|
+
exception.send(:include, Error)
|
15
|
+
end
|
16
|
+
|
17
|
+
class Node
|
18
|
+
class << self
|
19
|
+
def new_cdata(content)
|
20
|
+
REXML::CData.new(content)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
alias_attribute :content, :text
|
25
|
+
|
26
|
+
def search(xpath)
|
27
|
+
begin
|
28
|
+
REXML::XPath.match(self, xpath)
|
29
|
+
rescue Exception => ex
|
30
|
+
raise ex, xpath
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def add_child(element)
|
35
|
+
if element.is_a?(REXML::CData)
|
36
|
+
REXML::CData.new(element, true, self)
|
37
|
+
else
|
38
|
+
add_element(element)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def ==(other)
|
43
|
+
to_s == other.to_s
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class Parser
|
48
|
+
class << self
|
49
|
+
def parse(source)
|
50
|
+
REXML::Document.new(source, :ignore_whitespace_nodes => :all)
|
51
|
+
end
|
52
|
+
|
53
|
+
def parse_file(path) #:nodoc:
|
54
|
+
path = path.sub('file:', '') if path.starts_with?('file:')
|
55
|
+
parse(open(path))
|
56
|
+
end
|
57
|
+
|
58
|
+
def parse_io(path) #:nodoc:
|
59
|
+
parse(path)
|
60
|
+
end
|
61
|
+
|
62
|
+
def register_error_handler(&block)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
ParseError = REXML::ParseException
|
66
|
+
end
|
67
|
+
|
68
|
+
class Document
|
69
|
+
delegate :search, :to => :root
|
70
|
+
|
71
|
+
def root=(node)
|
72
|
+
raise ArgumentError, "Root is already defined" if root
|
73
|
+
add(node)
|
74
|
+
end
|
75
|
+
|
76
|
+
def save(destination, opts = {:formatter => REXML::Formatters::Default.new})
|
77
|
+
self << REXML::XMLDecl.new unless xml_decl != REXML::XMLDecl.default # always output xml declaration
|
78
|
+
File.open(destination, "w") do |f|
|
79
|
+
opts[:formatter].write(self, f)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,299 @@
|
|
1
|
+
module ROXML
|
2
|
+
class RequiredElementMissing < Exception # :nodoc:
|
3
|
+
end
|
4
|
+
|
5
|
+
#
|
6
|
+
# Internal base class that represents an XML - Class binding.
|
7
|
+
#
|
8
|
+
class XMLRef # :nodoc:
|
9
|
+
delegate :required?, :array?, :blocks, :accessor, :default, :to => :opts
|
10
|
+
|
11
|
+
def initialize(opts, instance)
|
12
|
+
@opts = opts
|
13
|
+
@instance = instance
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_xml
|
17
|
+
val = @instance.__send__(accessor)
|
18
|
+
opts.to_xml.respond_to?(:call) ? opts.to_xml.call(val) : val
|
19
|
+
end
|
20
|
+
|
21
|
+
def update_xml(xml, value)
|
22
|
+
returning wrap(xml) do |xml|
|
23
|
+
write_xml(xml, value)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def name
|
28
|
+
opts.name_explicit? ? opts.name : conventionize(opts.name)
|
29
|
+
end
|
30
|
+
|
31
|
+
def xpath_name
|
32
|
+
if !opts.name_explicit? && namespace = @instance.class.roxml_namespace
|
33
|
+
"#{namespace}:#{name}"
|
34
|
+
else
|
35
|
+
name
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def value_in(xml)
|
40
|
+
xml = XML::Node.from(xml)
|
41
|
+
value = fetch_value(xml)
|
42
|
+
value = default if value.nil?
|
43
|
+
|
44
|
+
freeze(apply_blocks(value))
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
attr_reader :opts
|
49
|
+
|
50
|
+
def conventionize(what)
|
51
|
+
convention ||= @instance.class.respond_to?(:roxml_naming_convention) && @instance.class.roxml_naming_convention
|
52
|
+
if !what.blank? && convention.respond_to?(:call)
|
53
|
+
URI.unescape(convention.call(URI.escape(what, /\/|::/)))
|
54
|
+
else
|
55
|
+
what
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def wrapper
|
60
|
+
conventionize(opts.wrapper)
|
61
|
+
end
|
62
|
+
|
63
|
+
def apply_blocks(val)
|
64
|
+
begin
|
65
|
+
blocks.apply_to(val)
|
66
|
+
rescue Exception => ex
|
67
|
+
raise ex, "#{accessor}: #{ex.message}"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def freeze(val)
|
72
|
+
if opts.frozen?
|
73
|
+
val.each(&:freeze) if val.is_a?(Enumerable)
|
74
|
+
val.freeze
|
75
|
+
else
|
76
|
+
val
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def xpath
|
81
|
+
wrapper ? "#{wrapper}/#{xpath_name}" : xpath_name.to_s
|
82
|
+
end
|
83
|
+
|
84
|
+
def auto_xpath
|
85
|
+
"#{conventionize(opts.name.pluralize)}/#{xpath_name}" if array?
|
86
|
+
end
|
87
|
+
|
88
|
+
def wrap(xml)
|
89
|
+
return xml if !wrapper || xml.name == wrapper
|
90
|
+
if child = xml.children.find {|c| c.name == wrapper }
|
91
|
+
return child
|
92
|
+
end
|
93
|
+
xml.add_child(XML::Node.new(wrapper.to_s))
|
94
|
+
end
|
95
|
+
|
96
|
+
def nodes_in(xml)
|
97
|
+
vals = xml.search(xpath)
|
98
|
+
|
99
|
+
if (opts.hash? || opts.array?) && vals.empty? && !wrapper && auto_xpath
|
100
|
+
vals = xml.search(auto_xpath)
|
101
|
+
@auto_vals = !vals.empty?
|
102
|
+
end
|
103
|
+
|
104
|
+
if vals.empty?
|
105
|
+
raise RequiredElementMissing, "#{name} from #{xml} for #{accessor}" if required?
|
106
|
+
default
|
107
|
+
else
|
108
|
+
yield(vals)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
# Interal class representing an XML attribute binding
|
114
|
+
#
|
115
|
+
# In context:
|
116
|
+
# <element attribute="XMLAttributeRef">
|
117
|
+
# XMLTextRef
|
118
|
+
# </element>
|
119
|
+
class XMLAttributeRef < XMLRef # :nodoc:
|
120
|
+
private
|
121
|
+
# Updates the attribute in the given XML block to
|
122
|
+
# the value provided.
|
123
|
+
def write_xml(xml, value)
|
124
|
+
xml.attributes[name] = value.to_s
|
125
|
+
end
|
126
|
+
|
127
|
+
def fetch_value(xml)
|
128
|
+
nodes_in(xml) do |nodes|
|
129
|
+
nodes.first.value
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def xpath_name
|
134
|
+
"@#{name}"
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
# Interal class representing XML content text binding
|
139
|
+
#
|
140
|
+
# In context:
|
141
|
+
# <element attribute="XMLAttributeRef">
|
142
|
+
# XMLTextRef
|
143
|
+
# </element>
|
144
|
+
class XMLTextRef < XMLRef # :nodoc:
|
145
|
+
delegate :cdata?, :content?, :name?, :to => :opts
|
146
|
+
|
147
|
+
private
|
148
|
+
# Updates the text in the given _xml_ block to
|
149
|
+
# the _value_ provided.
|
150
|
+
def write_xml(xml, value)
|
151
|
+
if content?
|
152
|
+
add(xml, value)
|
153
|
+
elsif name?
|
154
|
+
xml.name = value
|
155
|
+
elsif array?
|
156
|
+
value.each do |v|
|
157
|
+
add(xml.add_child(XML::Node.new(name)), v)
|
158
|
+
end
|
159
|
+
else
|
160
|
+
add(xml.add_child(XML::Node.new(name)), value)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def fetch_value(xml)
|
165
|
+
if content? || name?
|
166
|
+
value =
|
167
|
+
if content?
|
168
|
+
xml.content.to_s.strip
|
169
|
+
elsif name?
|
170
|
+
xml.name
|
171
|
+
end
|
172
|
+
|
173
|
+
if value.empty?
|
174
|
+
raise RequiredElementMissing, "#{name} from #{xml} for #{accessor}" if required?
|
175
|
+
default
|
176
|
+
else
|
177
|
+
value
|
178
|
+
end
|
179
|
+
else
|
180
|
+
nodes_in(xml) do |nodes|
|
181
|
+
if array?
|
182
|
+
nodes.collect do |e|
|
183
|
+
e.content.strip
|
184
|
+
end
|
185
|
+
else
|
186
|
+
nodes.first.content
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
def add(dest, value)
|
193
|
+
if cdata?
|
194
|
+
dest.child_add(XML::Node.new_cdata(value.to_s))
|
195
|
+
else
|
196
|
+
dest.content = value.to_s
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
class XMLHashRef < XMLTextRef # :nodoc:
|
202
|
+
delegate :hash, :to => :opts
|
203
|
+
|
204
|
+
def initialize(opts, inst)
|
205
|
+
super(opts, inst)
|
206
|
+
@key = opts.hash.key.to_ref(inst)
|
207
|
+
@value = opts.hash.value.to_ref(inst)
|
208
|
+
end
|
209
|
+
|
210
|
+
private
|
211
|
+
# Updates the composed XML object in the given XML block to
|
212
|
+
# the value provided.
|
213
|
+
def write_xml(xml, value)
|
214
|
+
value.each_pair do |k, v|
|
215
|
+
node = xml.child_add(XML::Node.new(hash.wrapper))
|
216
|
+
@key.update_xml(node, k)
|
217
|
+
@value.update_xml(node, v)
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
def fetch_value(xml)
|
222
|
+
nodes_in(xml) do |nodes|
|
223
|
+
nodes.collect do |e|
|
224
|
+
[@key.value_in(e), @value.value_in(e)]
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
def apply_blocks(vals)
|
230
|
+
unless blocks.empty?
|
231
|
+
vals.collect! do |kvp|
|
232
|
+
super(kvp)
|
233
|
+
end
|
234
|
+
end
|
235
|
+
to_hash(vals) if vals
|
236
|
+
end
|
237
|
+
|
238
|
+
def freeze(vals)
|
239
|
+
if opts.frozen?
|
240
|
+
vals.each_pair{|k, v| k.freeze; v.freeze }
|
241
|
+
vals.freeze
|
242
|
+
else
|
243
|
+
vals
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
def to_hash(array)
|
248
|
+
hash = array.inject({}) do |result, (k, v)|
|
249
|
+
result[k] ||= []
|
250
|
+
result[k] << v
|
251
|
+
result
|
252
|
+
end
|
253
|
+
hash.each_pair do |k, v|
|
254
|
+
hash[k] = v.first if v.one?
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
class XMLObjectRef < XMLTextRef # :nodoc:
|
260
|
+
delegate :type, :to => :opts
|
261
|
+
|
262
|
+
private
|
263
|
+
# Updates the composed XML object in the given XML block to
|
264
|
+
# the value provided.
|
265
|
+
def write_xml(xml, value)
|
266
|
+
if array?
|
267
|
+
value.each do |v|
|
268
|
+
xml.child_add(v.to_xml(name))
|
269
|
+
end
|
270
|
+
elsif value.is_a?(ROXML)
|
271
|
+
xml.child_add(value.to_xml(name))
|
272
|
+
else
|
273
|
+
node = XML::Node.new(name)
|
274
|
+
node.content = value.to_xml
|
275
|
+
xml.child_add(node)
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
def fetch_value(xml)
|
280
|
+
nodes_in(xml) do |nodes|
|
281
|
+
unless array?
|
282
|
+
instantiate(nodes.first)
|
283
|
+
else
|
284
|
+
nodes.collect do |e|
|
285
|
+
instantiate(e)
|
286
|
+
end
|
287
|
+
end
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
def instantiate(elem)
|
292
|
+
if type.respond_to? :from_xml
|
293
|
+
type.from_xml(elem)
|
294
|
+
else
|
295
|
+
type.new(elem)
|
296
|
+
end
|
297
|
+
end
|
298
|
+
end
|
299
|
+
end
|
data/roxml.gemspec
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{roxml}
|
5
|
+
s.version = "2.5.3"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Ben Woosley", "Zak Mandhro", "Anders Engstrom", "Russ Olsen"]
|
9
|
+
s.date = %q{2009-03-22}
|
10
|
+
s.description = %q{ROXML is a Ruby library designed to make it easier for Ruby developers to work with XML. Using simple annotations, it enables Ruby classes to be mapped to XML. ROXML takes care of the marshalling and unmarshalling of mapped attributes so that developers can focus on building first-class Ruby classes. As a result, ROXML simplifies the development of RESTful applications, Web Services, and XML-RPC.}
|
11
|
+
s.email = %q{ben.woosley@gmail.com}
|
12
|
+
s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.rdoc"]
|
13
|
+
s.files = ["History.txt", "MIT-LICENSE", "Manifest.txt", "README.rdoc", "Rakefile", "TODO", "config/website.yml", "examples/active_record.rb", "examples/amazon.rb", "examples/current_weather.rb", "examples/dashed_elements.rb", "examples/library.rb", "examples/posts.rb", "examples/twitter.rb", "examples/xml/active_record.xml", "examples/xml/amazon.xml", "examples/xml/current_weather.xml", "examples/xml/dashed_elements.xml", "examples/xml/posts.xml", "examples/xml/twitter.xml", "lib/roxml.rb", "lib/roxml/definition.rb", "lib/roxml/extensions.rb", "lib/roxml/extensions/array.rb", "lib/roxml/extensions/array/conversions.rb", "lib/roxml/extensions/deprecation.rb", "lib/roxml/extensions/string.rb", "lib/roxml/extensions/string/conversions.rb", "lib/roxml/extensions/string/iterators.rb", "lib/roxml/hash_definition.rb", "lib/roxml/xml.rb", "lib/roxml/xml/parsers/libxml.rb", "lib/roxml/xml/parsers/rexml.rb", "lib/roxml/xml/references.rb", "roxml.gemspec", "spec/definition_spec.rb", "spec/examples/active_record_spec.rb", "spec/examples/amazon_spec.rb", "spec/examples/current_weather_spec.rb", "spec/examples/dashed_elements_spec.rb", "spec/examples/library_spec.rb", "spec/examples/post_spec.rb", "spec/examples/twitter_spec.rb", "spec/roxml_spec.rb", "spec/shared_specs.rb", "spec/spec.opts", "spec/spec_helper.rb", "spec/xml/parser_spec.rb", "tasks/rspec.rake", "tasks/test.rake", "test/bugs/rexml_bugs.rb", "test/fixtures/book_malformed.xml", "test/fixtures/book_pair.xml", "test/fixtures/book_text_with_attribute.xml", "test/fixtures/book_valid.xml", "test/fixtures/book_with_authors.xml", "test/fixtures/book_with_contributions.xml", "test/fixtures/book_with_contributors.xml", "test/fixtures/book_with_contributors_attrs.xml", "test/fixtures/book_with_default_namespace.xml", "test/fixtures/book_with_depth.xml", "test/fixtures/book_with_octal_pages.xml", "test/fixtures/book_with_publisher.xml", "test/fixtures/book_with_wrapped_attr.xml", "test/fixtures/dictionary_of_attr_name_clashes.xml", "test/fixtures/dictionary_of_attrs.xml", "test/fixtures/dictionary_of_guarded_names.xml", "test/fixtures/dictionary_of_mixeds.xml", "test/fixtures/dictionary_of_name_clashes.xml", "test/fixtures/dictionary_of_names.xml", "test/fixtures/dictionary_of_texts.xml", "test/fixtures/library.xml", "test/fixtures/library_uppercase.xml", "test/fixtures/muffins.xml", "test/fixtures/nameless_ageless_youth.xml", "test/fixtures/node_with_attr_name_conflicts.xml", "test/fixtures/node_with_name_conflicts.xml", "test/fixtures/numerology.xml", "test/fixtures/person.xml", "test/fixtures/person_with_guarded_mothers.xml", "test/fixtures/person_with_mothers.xml", "test/mocks/dictionaries.rb", "test/mocks/mocks.rb", "test/test_helper.rb", "test/unit/definition_test.rb", "test/unit/deprecations_test.rb", "test/unit/to_xml_test.rb", "test/unit/xml_attribute_test.rb", "test/unit/xml_block_test.rb", "test/unit/xml_bool_test.rb", "test/unit/xml_convention_test.rb", "test/unit/xml_hash_test.rb", "test/unit/xml_initialize_test.rb", "test/unit/xml_name_test.rb", "test/unit/xml_namespace_test.rb", "test/unit/xml_object_test.rb", "test/unit/xml_required_test.rb", "test/unit/xml_text_test.rb", "vendor/override_rake_task/README", "vendor/override_rake_task/init.rb", "vendor/override_rake_task/install.rb", "vendor/override_rake_task/lib/override_rake_task.rb", "website/index.html"]
|
14
|
+
s.has_rdoc = true
|
15
|
+
s.homepage = %q{http://roxml.rubyforge.org}
|
16
|
+
s.rdoc_options = ["--main", "README.rdoc"]
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
s.rubyforge_project = %q{roxml}
|
19
|
+
s.rubygems_version = %q{1.3.1}
|
20
|
+
s.summary = %q{Ruby Object to XML mapping library}
|
21
|
+
s.test_files = ["test/unit/definition_test.rb", "test/unit/deprecations_test.rb", "test/unit/to_xml_test.rb", "test/unit/xml_attribute_test.rb", "test/unit/xml_block_test.rb", "test/unit/xml_bool_test.rb", "test/unit/xml_convention_test.rb", "test/unit/xml_hash_test.rb", "test/unit/xml_initialize_test.rb", "test/unit/xml_name_test.rb", "test/unit/xml_namespace_test.rb", "test/unit/xml_object_test.rb", "test/unit/xml_required_test.rb", "test/unit/xml_text_test.rb"]
|
22
|
+
|
23
|
+
if s.respond_to? :specification_version then
|
24
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
25
|
+
s.specification_version = 2
|
26
|
+
|
27
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
28
|
+
s.add_runtime_dependency(%q<activesupport>, [">= 2.1.0"])
|
29
|
+
s.add_runtime_dependency(%q<libxml-ruby>, [">= 1.0.0"])
|
30
|
+
s.add_development_dependency(%q<newgem>, [">= 1.3.0"])
|
31
|
+
s.add_development_dependency(%q<sqlite3-ruby>, [">= 1.2.4"])
|
32
|
+
s.add_development_dependency(%q<activerecord>, [">= 2.2.2"])
|
33
|
+
s.add_development_dependency(%q<hoe>, [">= 1.8.0"])
|
34
|
+
else
|
35
|
+
s.add_dependency(%q<activesupport>, [">= 2.1.0"])
|
36
|
+
s.add_dependency(%q<libxml-ruby>, [">= 1.0.0"])
|
37
|
+
s.add_dependency(%q<newgem>, [">= 1.3.0"])
|
38
|
+
s.add_dependency(%q<sqlite3-ruby>, [">= 1.2.4"])
|
39
|
+
s.add_dependency(%q<activerecord>, [">= 2.2.2"])
|
40
|
+
s.add_dependency(%q<hoe>, [">= 1.8.0"])
|
41
|
+
end
|
42
|
+
else
|
43
|
+
s.add_dependency(%q<activesupport>, [">= 2.1.0"])
|
44
|
+
s.add_dependency(%q<libxml-ruby>, [">= 1.0.0"])
|
45
|
+
s.add_dependency(%q<newgem>, [">= 1.3.0"])
|
46
|
+
s.add_dependency(%q<sqlite3-ruby>, [">= 1.2.4"])
|
47
|
+
s.add_dependency(%q<activerecord>, [">= 2.2.2"])
|
48
|
+
s.add_dependency(%q<hoe>, [">= 1.8.0"])
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,490 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
+
|
3
|
+
class RoxmlObject
|
4
|
+
include ROXML
|
5
|
+
end
|
6
|
+
|
7
|
+
describe ROXML::Definition do
|
8
|
+
describe "#name_explicit?" do
|
9
|
+
it "should indicate whether from option is present" do
|
10
|
+
ROXML::Definition.new(:element, :from => 'somewhere').name_explicit?.should be_true
|
11
|
+
ROXML::Definition.new(:element).name_explicit?.should be_false
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should not consider name proxies as explicit" do
|
15
|
+
ROXML::Definition.new(:element, :from => :attr).name_explicit?.should be_false
|
16
|
+
ROXML::Definition.new(:element, :from => :content).name_explicit?.should be_false
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "DateTime reference", :shared => true do
|
21
|
+
it "should return nil on empty string" do
|
22
|
+
@subject.blocks.first.call(" ").should be_nil
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should return a time version of the string" do
|
26
|
+
@subject.blocks.first.call("12:05pm, September 3rd, 1970").to_s == "1970-09-03T12:05:00+00:00"
|
27
|
+
end
|
28
|
+
|
29
|
+
context "when passed an array of values" do
|
30
|
+
it "should timify all of them" do
|
31
|
+
@subject.blocks.first.call(["12:05pm, September 3rd, 1970", "3:00pm, May 22, 1700"]).map(&:to_s).should == ["1970-09-03T12:05:00+00:00", "1700-05-22T15:00:00+00:00"]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "Date reference", :shared => true do
|
37
|
+
it "should return nil on empty string" do
|
38
|
+
@subject.blocks.first.call(" ").should be_nil
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should return a time version of the string" do
|
42
|
+
@subject.blocks.first.call("September 3rd, 1970").to_s == "1970-09-03"
|
43
|
+
end
|
44
|
+
|
45
|
+
context "when passed an array of values" do
|
46
|
+
it "should timify all of them" do
|
47
|
+
@subject.blocks.first.call(["September 3rd, 1970", "1776-07-04"]).map(&:to_s).should == ["1970-09-03", "1776-07-04"]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should unescape xml entities" do
|
53
|
+
ROXML::Definition.new(:questions, :as => []).to_ref(RoxmlObject.new).value_in(%{
|
54
|
+
<xml>
|
55
|
+
<question>"Wickard & Filburn" ></question>
|
56
|
+
<question> < McCulloch & Maryland?</question>
|
57
|
+
</xml>
|
58
|
+
}).should == ["\"Wickard & Filburn\" >", "< McCulloch & Maryland?"]
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "attr name" do
|
62
|
+
context "when ending with '_at'" do
|
63
|
+
context "and without an :as argument" do
|
64
|
+
before(:all) do
|
65
|
+
@subject = ROXML::Definition.new(:time_at)
|
66
|
+
end
|
67
|
+
it_should_behave_like "DateTime reference"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context "when ending with '_on'" do
|
72
|
+
context "and without an :as argument" do
|
73
|
+
before(:all) do
|
74
|
+
@subject = ROXML::Definition.new(:created_on)
|
75
|
+
end
|
76
|
+
it_should_behave_like "Date reference"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe ":as" do
|
82
|
+
describe "=> []" do
|
83
|
+
it "should means array of texts" do
|
84
|
+
opts = ROXML::Definition.new(:authors, :as => [])
|
85
|
+
opts.array?.should be_true
|
86
|
+
opts.type.should == :text
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe "=> RoxmlClass" do
|
91
|
+
class RoxmlClass
|
92
|
+
include ROXML
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should store type" do
|
96
|
+
opts = ROXML::Definition.new(:name, :as => RoxmlClass)
|
97
|
+
opts.type.should == RoxmlClass
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
describe "=> NonRoxmlClassWithFromXmlDefined" do
|
102
|
+
class OctalInteger
|
103
|
+
def self.from_xml(val)
|
104
|
+
new(Integer(val.content))
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
it "should accept type" do
|
109
|
+
opts = ROXML::Definition.new(:name, :as => OctalInteger)
|
110
|
+
opts.type.should == OctalInteger
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
describe "=> NonRoxmlClass" do
|
115
|
+
it "should fail with a warning" do
|
116
|
+
proc { ROXML::Definition.new(:authors, :as => Module) }.should raise_error(ArgumentError)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
describe "=> [NonRoxmlClass]" do
|
121
|
+
it "should raise" do
|
122
|
+
proc { ROXML::Definition.new(:authors, :as => [Module]) }.should raise_error(ArgumentError)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
describe "=> {}" do
|
127
|
+
describe "hash options declaration", :shared => true do
|
128
|
+
it "should represent a hash" do
|
129
|
+
@opts.hash?.should be_true
|
130
|
+
end
|
131
|
+
|
132
|
+
it "should have hash definition" do
|
133
|
+
{@opts.hash.key.type => @opts.hash.key.name}.should == @hash_args[:key]
|
134
|
+
{@opts.hash.value.type => @opts.hash.value.name}.should == @hash_args[:value]
|
135
|
+
end
|
136
|
+
|
137
|
+
it "should not represent an array" do
|
138
|
+
@opts.array?.should be_false
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
describe "hash with attr key and text val" do
|
143
|
+
before do
|
144
|
+
@opts = ROXML::Definition.new(:attributes, :as => {:key => '@name',
|
145
|
+
:value => 'value'})
|
146
|
+
@hash_args = {:key => {:attr => 'name'},
|
147
|
+
:value => {:text => 'value'}}
|
148
|
+
end
|
149
|
+
|
150
|
+
it_should_behave_like "hash options declaration"
|
151
|
+
end
|
152
|
+
|
153
|
+
describe "hash with String class for type" do
|
154
|
+
before do
|
155
|
+
@opts = ROXML::Definition.new(:attributes, :as => {:key => 'name',
|
156
|
+
:value => 'value'})
|
157
|
+
@hash_args = {:key => {:text => 'name'}, :value => {:text => 'value'}}
|
158
|
+
end
|
159
|
+
|
160
|
+
it_should_behave_like "hash options declaration"
|
161
|
+
end
|
162
|
+
|
163
|
+
describe "hash with attr key and content val" do
|
164
|
+
before do
|
165
|
+
@opts = ROXML::Definition.new(:attributes, :as => {:key => '@name',
|
166
|
+
:value => :content})
|
167
|
+
@hash_args = {:key => {:attr => 'name'}, :value => {:text => '.'}}
|
168
|
+
end
|
169
|
+
|
170
|
+
it_should_behave_like "hash options declaration"
|
171
|
+
end
|
172
|
+
|
173
|
+
describe "hash with names as keys and content vals" do
|
174
|
+
before do
|
175
|
+
@opts = ROXML::Definition.new(:attributes, :as => {:key => :name,
|
176
|
+
:value => :content})
|
177
|
+
@hash_args = {:key => {:text => '*'}, :value => {:text => '.'}}
|
178
|
+
end
|
179
|
+
|
180
|
+
it_should_behave_like "hash options declaration"
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
describe "for block shorthand" do
|
185
|
+
describe "in literal array" do
|
186
|
+
before do
|
187
|
+
@opts = ROXML::Definition.new(:intarray, :as => [Integer])
|
188
|
+
end
|
189
|
+
|
190
|
+
it "should be detected as array reference" do
|
191
|
+
@opts.array?.should be_true
|
192
|
+
end
|
193
|
+
|
194
|
+
it "should be normal otherwise" do
|
195
|
+
@opts.type.should == :text
|
196
|
+
@opts.blocks.size.should == 1
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
it "should have no blocks without a shorthand" do
|
201
|
+
ROXML::Definition.new(:count).blocks.should be_empty
|
202
|
+
end
|
203
|
+
|
204
|
+
it "should raise on unknown :as" do
|
205
|
+
proc { ROXML::Definition.new(:count, :as => :bogus) }.should raise_error(ArgumentError)
|
206
|
+
proc { ROXML::Definition.new(:count, :as => :foat) }.should raise_error(ArgumentError)
|
207
|
+
end
|
208
|
+
|
209
|
+
describe "block shorthand type declaration", :shared => true do
|
210
|
+
it "should translate nil to nil" do
|
211
|
+
@definition.blocks.first.call(nil).should be_nil
|
212
|
+
end
|
213
|
+
|
214
|
+
it "should translate empty strings to nil" do
|
215
|
+
@definition.blocks.first.call("").should be_nil
|
216
|
+
@definition.blocks.first.call(" ").should be_nil
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
describe "Integer" do
|
221
|
+
before do
|
222
|
+
@definition = ROXML::Definition.new(:intvalue, :as => Integer)
|
223
|
+
end
|
224
|
+
|
225
|
+
it_should_behave_like "block shorthand type declaration"
|
226
|
+
|
227
|
+
it "should translate text to integers" do
|
228
|
+
@definition.blocks.first['3'].should == 3
|
229
|
+
@definition.blocks.first['792'].should == 792
|
230
|
+
end
|
231
|
+
|
232
|
+
it "should raise on non-integer values" do
|
233
|
+
proc { @definition.blocks.first['08'] }.should raise_error(ArgumentError)
|
234
|
+
proc { @definition.blocks.first['793.12'] }.should raise_error(ArgumentError)
|
235
|
+
proc { @definition.blocks.first['junk 11'] }.should raise_error(ArgumentError)
|
236
|
+
proc { @definition.blocks.first['11sttf'] }.should raise_error(ArgumentError)
|
237
|
+
end
|
238
|
+
|
239
|
+
context "when passed an array" do
|
240
|
+
it "should translate the array elements to integer" do
|
241
|
+
@definition.blocks.first.call(["792", "12", "328"]).should == [792, 12, 328]
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
describe "Float" do
|
247
|
+
before do
|
248
|
+
@definition = ROXML::Definition.new(:floatvalue, :as => Float)
|
249
|
+
end
|
250
|
+
|
251
|
+
it_should_behave_like "block shorthand type declaration"
|
252
|
+
|
253
|
+
it "should translate text to float" do
|
254
|
+
@definition.blocks.first['3'].should == 3.0
|
255
|
+
@definition.blocks.first['12.7'].should == 12.7
|
256
|
+
end
|
257
|
+
|
258
|
+
it "should raise on non-float values" do
|
259
|
+
proc { @definition.blocks.first['junk 11.3'] }.should raise_error(ArgumentError)
|
260
|
+
proc { @definition.blocks.first['11.1sttf'] }.should raise_error(ArgumentError)
|
261
|
+
end
|
262
|
+
|
263
|
+
context "when passed an array" do
|
264
|
+
it "should translate the array elements to integer" do
|
265
|
+
@definition.blocks.first.call(["792.13", "240", "3.14"]).should == [792.13, 240.0, 3.14]
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
describe "BigDecimal" do
|
271
|
+
before do
|
272
|
+
@definition = ROXML::Definition.new(:decimalvalue, :as => BigDecimal)
|
273
|
+
end
|
274
|
+
|
275
|
+
it_should_behave_like "block shorthand type declaration"
|
276
|
+
|
277
|
+
it "should translate text to decimal numbers" do
|
278
|
+
@definition.blocks.first['3'].should == BigDecimal.new("3.0")
|
279
|
+
@definition.blocks.first['0.3'].should == BigDecimal.new("0.3")
|
280
|
+
end
|
281
|
+
|
282
|
+
it "should extract what it can, and fall back to 0" do
|
283
|
+
@definition.blocks.first['junk 11'].should eql(BigDecimal.new("0"))
|
284
|
+
@definition.blocks.first['11sttf'].should eql(BigDecimal.new("11.0"))
|
285
|
+
end
|
286
|
+
|
287
|
+
context "when passed an array" do
|
288
|
+
it "should translate the array elements to integer" do
|
289
|
+
@definition.blocks.first.call(["12.1", "328.2"]).should == [BigDecimal.new("12.1"), BigDecimal.new("328.2")]
|
290
|
+
end
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
describe "Fixnum" do
|
295
|
+
before do
|
296
|
+
@definition = ROXML::Definition.new(:fixnumvalue, :as => Fixnum)
|
297
|
+
end
|
298
|
+
|
299
|
+
it_should_behave_like "block shorthand type declaration"
|
300
|
+
|
301
|
+
it "should translate text to integers" do
|
302
|
+
@definition.blocks.first['3'].should == 3
|
303
|
+
@definition.blocks.first['792'].should == 792
|
304
|
+
@definition.blocks.first['08'].should == 8
|
305
|
+
@definition.blocks.first['279.23'].should == 279
|
306
|
+
end
|
307
|
+
|
308
|
+
it "should extract whatever is possible and fall back to 0" do
|
309
|
+
@definition.blocks.first['junk 11'].should eql(0)
|
310
|
+
@definition.blocks.first['.?sttf'].should eql(0)
|
311
|
+
@definition.blocks.first['11sttf'].should eql(11)
|
312
|
+
end
|
313
|
+
|
314
|
+
context "when passed an array" do
|
315
|
+
it "should translate the array elements to integer" do
|
316
|
+
@definition.blocks.first.call(["792", "12", "328"]).should == [792, 12, 328]
|
317
|
+
end
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
describe ":bool" do
|
322
|
+
it "should boolify individual values" do
|
323
|
+
ROXML::Definition.new(:floatvalue, :as => :bool).blocks.first.call("1").should be_true
|
324
|
+
ROXML::Definition.new(:floatvalue, :as => :bool).blocks.first.call("True").should be_true
|
325
|
+
ROXML::Definition.new(:floatvalue, :as => :bool).blocks.first.call("Yes").should be_true
|
326
|
+
end
|
327
|
+
|
328
|
+
context "when an array is passed in" do
|
329
|
+
it "should boolify arrays of values" do
|
330
|
+
ROXML::Definition.new(:floatvalue, :as => :bool).blocks.first.call("0").should be_false
|
331
|
+
ROXML::Definition.new(:floatvalue, :as => :bool).blocks.first.call("false").should be_false
|
332
|
+
ROXML::Definition.new(:floatvalue, :as => :bool).blocks.first.call("nO").should be_false
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
context "when no value is detected" do
|
337
|
+
it "should return nil" do
|
338
|
+
ROXML::Definition.new(:floatvalue, :as => :bool).blocks.first.call("junk").should be_nil
|
339
|
+
end
|
340
|
+
|
341
|
+
context "when a literal block is available" do
|
342
|
+
it "should pass the value itself to the block"
|
343
|
+
end
|
344
|
+
end
|
345
|
+
end
|
346
|
+
|
347
|
+
describe "Time" do
|
348
|
+
it "should return nil on empty string" do
|
349
|
+
ROXML::Definition.new(:floatvalue, :as => Time).blocks.first.call(" ").should be_nil
|
350
|
+
end
|
351
|
+
|
352
|
+
it "should return a time version of the string" do
|
353
|
+
ROXML::Definition.new(:datevalue, :as => Time).blocks.first.call("12:31am").min.should == 31
|
354
|
+
end
|
355
|
+
|
356
|
+
context "when passed an array of values" do
|
357
|
+
it "should timify all of them" do
|
358
|
+
ROXML::Definition.new(:datevalue, :as => Time).blocks.first.call(["12:31am", "3:00pm", "11:59pm"]).map(&:min).should == [31, 0, 59]
|
359
|
+
end
|
360
|
+
end
|
361
|
+
end
|
362
|
+
|
363
|
+
describe "Date" do
|
364
|
+
before do
|
365
|
+
@subject = ROXML::Definition.new(:datevalue, :as => Date)
|
366
|
+
end
|
367
|
+
it_should_behave_like "Date reference"
|
368
|
+
end
|
369
|
+
|
370
|
+
describe "DateTime" do
|
371
|
+
before do
|
372
|
+
@subject = ROXML::Definition.new(:datevalue, :as => DateTime)
|
373
|
+
end
|
374
|
+
it_should_behave_like "DateTime reference"
|
375
|
+
end
|
376
|
+
|
377
|
+
it "should prohibit multiple shorthands" do
|
378
|
+
proc { ROXML::Definition.new(:count, :as => [Float, Integer]) }.should raise_error(ArgumentError)
|
379
|
+
end
|
380
|
+
|
381
|
+
it "should stack block shorthands with explicit blocks" do
|
382
|
+
ROXML::Definition.new(:count, :as => Integer) {|val| val.to_i }.blocks.size.should == 2
|
383
|
+
ROXML::Definition.new(:count, :as => Float) {|val| val.object_id }.blocks.size.should == 2
|
384
|
+
end
|
385
|
+
end
|
386
|
+
end
|
387
|
+
|
388
|
+
describe ":from" do
|
389
|
+
describe "attribute reference", :shared => true do
|
390
|
+
it "should be interpreted as :attr" do
|
391
|
+
@opts.type.should == :attr
|
392
|
+
end
|
393
|
+
|
394
|
+
it "should strip '@' from name" do
|
395
|
+
@opts.name.should == 'attr_name'
|
396
|
+
end
|
397
|
+
|
398
|
+
it "should unescape xml entities" do
|
399
|
+
@opts.to_ref(RoxmlObject.new).value_in(%{
|
400
|
+
<question attr_name=""Wickard & Filburn" > / < McCulloch & Marryland?" />
|
401
|
+
}).should == "\"Wickard & Filburn\" > / < McCulloch & Marryland?"
|
402
|
+
end
|
403
|
+
end
|
404
|
+
|
405
|
+
context ":attr" do
|
406
|
+
before do
|
407
|
+
@opts = ROXML::Definition.new(:attr_name, :from => :attr)
|
408
|
+
end
|
409
|
+
|
410
|
+
it_should_behave_like "attribute reference"
|
411
|
+
end
|
412
|
+
|
413
|
+
context "@attribute_name" do
|
414
|
+
before do
|
415
|
+
@opts = ROXML::Definition.new(:attr_name, :from => '@attr_name')
|
416
|
+
end
|
417
|
+
|
418
|
+
it_should_behave_like "attribute reference"
|
419
|
+
end
|
420
|
+
|
421
|
+
describe ":content" do
|
422
|
+
it "should be recognized" do
|
423
|
+
ROXML::Definition.new(:author).content?.should be_false
|
424
|
+
ROXML::Definition.new(:author, :from => :content).content?.should == true
|
425
|
+
end
|
426
|
+
|
427
|
+
it "should be equivalent to :from => '.'" do
|
428
|
+
ROXML::Definition.new(:author, :from => '.').content?.should == true
|
429
|
+
end
|
430
|
+
end
|
431
|
+
end
|
432
|
+
|
433
|
+
describe ":in" do
|
434
|
+
context "as xpath" do
|
435
|
+
it "should pass through as wrapper" do
|
436
|
+
ROXML::Definition.new(:manufacturer, :in => './').wrapper.should == './'
|
437
|
+
end
|
438
|
+
end
|
439
|
+
|
440
|
+
context "as xpath" do
|
441
|
+
it "should pass through as wrapper" do
|
442
|
+
ROXML::Definition.new(:manufacturer, :in => 'wrapper').wrapper.should == 'wrapper'
|
443
|
+
end
|
444
|
+
end
|
445
|
+
end
|
446
|
+
|
447
|
+
describe "options" do
|
448
|
+
|
449
|
+
describe "boolean option", :shared => true do
|
450
|
+
it "should be recognized" do
|
451
|
+
ROXML::Definition.new(:author, :from => :content, @option => true).respond_to?(:"#{@option}?")
|
452
|
+
ROXML::Definition.new(:author, :from => :content, @option => true).send(:"#{@option}?").should be_true
|
453
|
+
ROXML::Definition.new(:author, :from => :content, @option => false).send(:"#{@option}?").should be_false
|
454
|
+
end
|
455
|
+
|
456
|
+
it "should default to false" do
|
457
|
+
ROXML::Definition.new(:author, :from => :content).send(:"#{@option}?").should be_false
|
458
|
+
end
|
459
|
+
end
|
460
|
+
|
461
|
+
describe ":required" do
|
462
|
+
before do
|
463
|
+
@option = :required
|
464
|
+
end
|
465
|
+
|
466
|
+
it_should_behave_like "boolean option"
|
467
|
+
|
468
|
+
it "should not be allowed together with :else" do
|
469
|
+
proc { ROXML::Definition.new(:author, :from => :content, :required => true, :else => 'Johnny') }.should raise_error(ArgumentError)
|
470
|
+
proc { ROXML::Definition.new(:author, :from => :content, :required => false, :else => 'Johnny') }.should_not raise_error
|
471
|
+
end
|
472
|
+
end
|
473
|
+
|
474
|
+
describe ":frozen" do
|
475
|
+
before do
|
476
|
+
@option = :frozen
|
477
|
+
end
|
478
|
+
|
479
|
+
it_should_behave_like "boolean option"
|
480
|
+
end
|
481
|
+
|
482
|
+
describe ":cdata" do
|
483
|
+
before do
|
484
|
+
@option = :cdata
|
485
|
+
end
|
486
|
+
|
487
|
+
it_should_behave_like "boolean option"
|
488
|
+
end
|
489
|
+
end
|
490
|
+
end
|