yob-roxml 3.1.6
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/.gitignore +7 -0
- data/.gitmodules +3 -0
- data/History.txt +354 -0
- data/LICENSE +20 -0
- data/README.rdoc +195 -0
- data/Rakefile +117 -0
- data/TODO +37 -0
- data/VERSION +1 -0
- data/examples/amazon.rb +35 -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/rails.rb +70 -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 +556 -0
- data/lib/roxml/definition.rb +238 -0
- data/lib/roxml/hash_definition.rb +25 -0
- data/lib/roxml/xml.rb +40 -0
- data/lib/roxml/xml/parsers/libxml.rb +85 -0
- data/lib/roxml/xml/parsers/nokogiri.rb +82 -0
- data/lib/roxml/xml/references.rb +322 -0
- data/roxml.gemspec +206 -0
- data/spec/definition_spec.rb +494 -0
- data/spec/examples/active_record_spec.rb +40 -0
- data/spec/examples/amazon_spec.rb +54 -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 +14 -0
- data/spec/support/libxml.rb +3 -0
- data/spec/support/nokogiri.rb +3 -0
- data/spec/xml/array_spec.rb +36 -0
- data/spec/xml/attributes_spec.rb +71 -0
- data/spec/xml/encoding_spec.rb +52 -0
- data/spec/xml/namespace_spec.rb +270 -0
- data/spec/xml/namespaces_spec.rb +67 -0
- data/spec/xml/object_spec.rb +82 -0
- data/spec/xml/parser_spec.rb +21 -0
- data/spec/xml/text_spec.rb +71 -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/load_test.rb +6 -0
- data/test/mocks/dictionaries.rb +57 -0
- data/test/mocks/mocks.rb +279 -0
- data/test/support/fixtures.rb +11 -0
- data/test/test_helper.rb +34 -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 +31 -0
- data/test/unit/xml_object_test.rb +205 -0
- data/test/unit/xml_required_test.rb +94 -0
- data/test/unit/xml_text_test.rb +71 -0
- data/website/index.html +98 -0
- metadata +300 -0
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'test/test_helper'
|
2
|
+
|
3
|
+
class TestDeprecation < ActiveSupport::TestCase
|
4
|
+
def test_as_array_not_deprecated
|
5
|
+
assert_not_deprecated do
|
6
|
+
opts = ROXML::Definition.new(:name, :as => [])
|
7
|
+
assert_equal :text, opts.sought_type
|
8
|
+
assert opts.array?
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_as_hash_not_deprecated
|
13
|
+
assert_not_deprecated do
|
14
|
+
opts = ROXML::Definition.new(:name, :as => {:key => '@dt', :value => '@dd'})
|
15
|
+
assert opts.hash?
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_as_object_with_from_xml_not_deprecated
|
20
|
+
assert_not_deprecated do
|
21
|
+
ROXML::Definition.new(:name, :as => OctalInteger)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'test/test_helper'
|
2
|
+
|
3
|
+
class TestHashToXml < ActiveSupport::TestCase
|
4
|
+
to_xml_test :dictionary_of_attrs,
|
5
|
+
:dictionary_of_mixeds,
|
6
|
+
:dictionary_of_texts,
|
7
|
+
:dictionary_of_names,
|
8
|
+
:dictionary_of_guarded_names,
|
9
|
+
:dictionary_of_name_clashes,
|
10
|
+
:dictionary_of_attr_name_clashes
|
11
|
+
end
|
12
|
+
|
13
|
+
class TestOtherToXml < ActiveSupport::TestCase
|
14
|
+
to_xml_test :book => :book_valid,
|
15
|
+
:book_with_author_text_attribute => :book_text_with_attribute,
|
16
|
+
:uppercase_library => :library_uppercase
|
17
|
+
|
18
|
+
to_xml_test :book_with_authors,
|
19
|
+
:book_with_contributors,
|
20
|
+
:book_with_contributions,
|
21
|
+
:library,
|
22
|
+
:node_with_name_conflicts,
|
23
|
+
:node_with_attr_name_conflicts
|
24
|
+
|
25
|
+
to_xml_test :person_with_mother => :person_with_mothers,
|
26
|
+
:person_with_guarded_mother => :person_with_guarded_mothers
|
27
|
+
|
28
|
+
to_xml_test :book_with_wrapped_attr
|
29
|
+
end
|
30
|
+
|
31
|
+
class TestToXmlWithDefaults < ActiveSupport::TestCase
|
32
|
+
def test_content_and_attr_defaults_are_represented_in_output
|
33
|
+
dict = Person.from_xml(fixture(:nameless_ageless_youth))
|
34
|
+
|
35
|
+
xml = '<person age="21">Unknown</person>'
|
36
|
+
assert_equal ROXML::XML.parse_string(xml).root.to_s, dict.to_xml.to_s
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
class TestToXmlWithBlocks < ActiveSupport::TestCase
|
41
|
+
def test_pagecount_serialized_properly_after_modification
|
42
|
+
b = Book.from_xml(fixture(:book_valid))
|
43
|
+
xml = xml_fixture(:book_valid)
|
44
|
+
assert_equal '357', xml.roxml_search('pagecount').first.content
|
45
|
+
assert_equal 357, b.pages
|
46
|
+
|
47
|
+
b.pages = 500
|
48
|
+
doc = ROXML::XML::Document.new()
|
49
|
+
doc.root = b.to_xml
|
50
|
+
assert_equal '500', doc.roxml_search('pagecount').first.content
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
class OctalInteger
|
55
|
+
def self.from_xml(val)
|
56
|
+
new(Integer(val.content))
|
57
|
+
end
|
58
|
+
|
59
|
+
def initialize(value)
|
60
|
+
@val = value
|
61
|
+
end
|
62
|
+
|
63
|
+
def ==(other)
|
64
|
+
@val == other
|
65
|
+
end
|
66
|
+
|
67
|
+
def to_xml
|
68
|
+
sprintf("%#o", @val)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
class BookWithOctalPages
|
73
|
+
include ROXML
|
74
|
+
|
75
|
+
xml_accessor :pages_with_to_xml_proc, :as => Integer, :to_xml => proc {|val| sprintf("%#o", val) }, :required => true
|
76
|
+
xml_accessor :pages_with_type, :as => OctalInteger, :required => true
|
77
|
+
end
|
78
|
+
|
79
|
+
class TestToXmlWithOverriddenOutput < ActiveSupport::TestCase
|
80
|
+
to_xml_test :book_with_octal_pages
|
81
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'test/test_helper'
|
2
|
+
|
3
|
+
class TestXMLAttribute < ActiveSupport::TestCase
|
4
|
+
def test_attr_from
|
5
|
+
# :attr => *
|
6
|
+
book = Book.from_xml(fixture(:book_text_with_attribute))
|
7
|
+
assert_equal '0201710897', book.isbn
|
8
|
+
|
9
|
+
# :attr, :from => *
|
10
|
+
book = BookWithAttrFrom.from_xml(fixture(:book_text_with_attribute))
|
11
|
+
assert_equal '0201710897', book.isbn
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_mutable_attr
|
15
|
+
book = Book.from_xml(fixture(:book_text_with_attribute))
|
16
|
+
assert book.respond_to?(:'isbn=')
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_default_initialization
|
20
|
+
person = PersonWithMotherOrMissing.from_xml(fixture(:nameless_ageless_youth))
|
21
|
+
assert_equal 21, person.age
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_recursive_with_default_initialization
|
25
|
+
p = PersonWithMotherOrMissing.from_xml(fixture(:person_with_mothers))
|
26
|
+
assert_equal 21, p.mother.mother.mother.age
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_no_name_clashes
|
30
|
+
n = NodeWithAttrNameConflicts.from_xml(fixture(:node_with_attr_name_conflicts))
|
31
|
+
assert_equal "Just junk... really", n.content
|
32
|
+
assert_equal "Cartwheel", n.name
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_wrapped_attr_accessible
|
36
|
+
b = BookWithWrappedAttr.from_xml(fixture(:book_with_wrapped_attr))
|
37
|
+
assert_equal "0974514055", b.isbn
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'test/test_helper'
|
2
|
+
|
3
|
+
class ArrayWithBlockShorthand
|
4
|
+
include ROXML
|
5
|
+
|
6
|
+
xml_reader :array, :as => [Integer], :from => 'number'
|
7
|
+
end
|
8
|
+
|
9
|
+
class ArrayWithBlock
|
10
|
+
include ROXML
|
11
|
+
|
12
|
+
xml_reader :array, :as => [], :from => 'number' do |arr|
|
13
|
+
arr.map(&:to_i).reverse
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class TestXMLBlocks < ActiveSupport::TestCase
|
18
|
+
def test_block_is_applied
|
19
|
+
muffins = Muffins.from_xml(fixture(:muffins))
|
20
|
+
|
21
|
+
assert muffins.count > 0
|
22
|
+
assert_equal 0, muffins.count % 13
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_block_is_applied_to_hash
|
26
|
+
numerology = Numerology.from_xml(fixture(:numerology))
|
27
|
+
|
28
|
+
assert !numerology.predictions.keys.empty?
|
29
|
+
assert numerology.predictions.keys.all? {|k| k.is_a? Integer }
|
30
|
+
assert numerology.predictions.values.all? {|k| k.is_a? String }
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_stacked_blocks_are_applied
|
34
|
+
muffins = MuffinsWithStackedBlocks.from_xml(fixture(:muffins))
|
35
|
+
|
36
|
+
assert muffins.count > 0
|
37
|
+
assert_equal 0, muffins.count % 13
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_block_shorthand_applied_properly_to_array
|
41
|
+
obj = ArrayWithBlockShorthand.from_xml(%{
|
42
|
+
<array_with_block_shorthand>
|
43
|
+
<number>1</number>
|
44
|
+
<number>2</number>
|
45
|
+
<number>3</number>
|
46
|
+
</array_with_block_shorthand>
|
47
|
+
})
|
48
|
+
|
49
|
+
assert_equal [1, 2, 3], obj.array
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_block_applied_properly_to_array
|
53
|
+
obj = ArrayWithBlock.from_xml(%{
|
54
|
+
<array_with_block>
|
55
|
+
<number>1</number>
|
56
|
+
<number>2</number>
|
57
|
+
<number>3</number>
|
58
|
+
</array_with_block>
|
59
|
+
})
|
60
|
+
|
61
|
+
assert_equal [3, 2, 1], obj.array
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_block_shorthand_applied_properly_to_empty_array
|
65
|
+
obj = ArrayWithBlockShorthand.from_xml(%{
|
66
|
+
<array_with_block_shorthand>
|
67
|
+
</array_with_block_shorthand>
|
68
|
+
})
|
69
|
+
|
70
|
+
assert_equal [], obj.array
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_block_applied_properly_to_empty_array
|
74
|
+
obj = ArrayWithBlock.from_xml(%{
|
75
|
+
<array_with_block>
|
76
|
+
</array_with_block>
|
77
|
+
})
|
78
|
+
|
79
|
+
assert_equal [], obj.array
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
require 'test/test_helper'
|
2
|
+
|
3
|
+
PROC_TRUE = proc {|val| val ? 'TRUE' : 'FALSE'}
|
4
|
+
PROC_True = proc {|val| val ? 'True' : 'False'}
|
5
|
+
PROC_true = proc {|val| val.to_s}
|
6
|
+
PROC_1 = proc {|val| val ? 1 : 0}
|
7
|
+
|
8
|
+
class XmlBool
|
9
|
+
include ROXML
|
10
|
+
|
11
|
+
xml_name 'xml_bool'
|
12
|
+
xml_reader :true_from_TRUE?, :to_xml => PROC_TRUE
|
13
|
+
xml_reader :false_from_FALSE?, :from => 'text_for_FALSE', :to_xml => PROC_TRUE
|
14
|
+
xml_reader :true_from_one?, :from => '@attr_for_one', :to_xml => PROC_1
|
15
|
+
xml_reader :false_from_zero?, :from => 'text_for_zero', :in => 'container', :to_xml => PROC_1
|
16
|
+
xml_reader :true_from_True?, :from => '@attr_for_True', :in => 'container', :to_xml => PROC_True
|
17
|
+
xml_reader :false_from_False?, :from => 'false_from_cdata_False', :cdata => true, :to_xml => PROC_True
|
18
|
+
xml_reader :true_from_true?, :to_xml => PROC_true
|
19
|
+
xml_reader :false_from_false?, :to_xml => PROC_true
|
20
|
+
xml_reader :missing?
|
21
|
+
end
|
22
|
+
|
23
|
+
class XmlBoolRequired
|
24
|
+
include ROXML
|
25
|
+
|
26
|
+
xml_reader :required?, :required => true
|
27
|
+
end
|
28
|
+
|
29
|
+
class XmlBoolUnexpected
|
30
|
+
include ROXML
|
31
|
+
|
32
|
+
xml_reader :unexpected?
|
33
|
+
end
|
34
|
+
|
35
|
+
class XmlBoolUnexpectedWithBlock
|
36
|
+
include ROXML
|
37
|
+
|
38
|
+
xml_reader :unexpected? do |val|
|
39
|
+
val
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
BOOL_XML = %{
|
44
|
+
<xml_bool attr_for_one="1">
|
45
|
+
<true_from_TRUE>TRUE</true_from_TRUE>
|
46
|
+
<text_for_FALSE>FALSE</text_for_FALSE>
|
47
|
+
<container attr_for_True="True">
|
48
|
+
<text_for_zero>0</text_for_zero>
|
49
|
+
</container>
|
50
|
+
<false_from_cdata_False><![CDATA[False]]></false_from_cdata_False>
|
51
|
+
<true_from_true>true</true_from_true>
|
52
|
+
<false_from_false>false</false_from_false>
|
53
|
+
</xml_bool>
|
54
|
+
}
|
55
|
+
PRESENT = %{
|
56
|
+
<xml_bool_required>
|
57
|
+
<required>true</required>
|
58
|
+
</xml_bool_required>
|
59
|
+
}
|
60
|
+
ABSENT = %{
|
61
|
+
<xml_bool_required>
|
62
|
+
</xml_bool_required>
|
63
|
+
}
|
64
|
+
UNEXPECTED_VALUE_XML = %{
|
65
|
+
<xml_bool_unexpected>
|
66
|
+
<unexpected>Unexpected Value</unexpected>
|
67
|
+
</xml_bool_unexpected>
|
68
|
+
}
|
69
|
+
|
70
|
+
|
71
|
+
class TestXMLBool < ActiveSupport::TestCase
|
72
|
+
def test_bool_results_for_various_inputs
|
73
|
+
x = XmlBool.from_xml(BOOL_XML)
|
74
|
+
assert_equal true, x.true_from_TRUE?
|
75
|
+
assert_equal false, x.false_from_FALSE?
|
76
|
+
assert_equal true, x.true_from_one?
|
77
|
+
assert_equal false, x.false_from_zero?
|
78
|
+
assert_equal true, x.true_from_True?
|
79
|
+
assert_equal false, x.false_from_False?
|
80
|
+
assert_equal true, x.true_from_true?
|
81
|
+
assert_equal false, x.false_from_false?
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_missing_results_in_nil
|
85
|
+
x = XmlBool.from_xml(BOOL_XML)
|
86
|
+
assert_equal nil, x.missing?
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_unexpected_value_results_in_nil
|
90
|
+
x = XmlBoolUnexpected.from_xml(UNEXPECTED_VALUE_XML)
|
91
|
+
assert_equal nil, x.unexpected?
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_block_recieves_unexpected_value_rather_than_nil
|
95
|
+
x = XmlBoolUnexpectedWithBlock.from_xml(UNEXPECTED_VALUE_XML)
|
96
|
+
assert_equal "Unexpected Value", x.unexpected?
|
97
|
+
end
|
98
|
+
|
99
|
+
def test_required_raises_on_missing
|
100
|
+
assert_nothing_raised do
|
101
|
+
XmlBoolRequired.from_xml(PRESENT)
|
102
|
+
end
|
103
|
+
|
104
|
+
assert_raise ROXML::RequiredElementMissing do
|
105
|
+
XmlBoolRequired.from_xml(ABSENT)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def test_writable_references_properly_handle_punctuation
|
110
|
+
klass = Class.new do
|
111
|
+
include ROXML
|
112
|
+
xml_accessor :punctuation?
|
113
|
+
end
|
114
|
+
|
115
|
+
instance = klass.from_xml("<xml><punctuation>True</punctuation></xml>")
|
116
|
+
assert_equal true, instance.punctuation?
|
117
|
+
instance.punctuation = false
|
118
|
+
assert_equal false, instance.punctuation?
|
119
|
+
end
|
120
|
+
|
121
|
+
to_xml_test XmlBool => BOOL_XML
|
122
|
+
end
|
@@ -0,0 +1,150 @@
|
|
1
|
+
require 'test/test_helper'
|
2
|
+
|
3
|
+
XML_CAMELLOWER = %{
|
4
|
+
<bookCase name="Jonas' Books">
|
5
|
+
<bookCount>12</bookCount>
|
6
|
+
<bigBooks>
|
7
|
+
<bigBook>GED</bigBook>
|
8
|
+
<bigBook>House of Leaves</bigBook>
|
9
|
+
</bigBooks>
|
10
|
+
</bookCase>
|
11
|
+
}
|
12
|
+
|
13
|
+
XML_CAMELCASE = %{
|
14
|
+
<BookCase Name="Jonas' Books">
|
15
|
+
<BookCount>12</BookCount>
|
16
|
+
<BigBooks>
|
17
|
+
<BigBook>GED</BigBook>
|
18
|
+
<BigBook>House of Leaves</BigBook>
|
19
|
+
</BigBooks>
|
20
|
+
</BookCase>
|
21
|
+
}
|
22
|
+
|
23
|
+
XML_UNDERSCORE = %{
|
24
|
+
<book_case name="Jonas' Books">
|
25
|
+
<book_count>12</book_count>
|
26
|
+
<big_books>
|
27
|
+
<big_book>GED</big_book>
|
28
|
+
<big_book>House of Leaves</big_book>
|
29
|
+
</big_books>
|
30
|
+
</book_case>
|
31
|
+
}
|
32
|
+
|
33
|
+
XML_DASHES = %{
|
34
|
+
<book-case name="Jonas' Books">
|
35
|
+
<book-count>12</book-count>
|
36
|
+
<big-books>
|
37
|
+
<big-book>GED</big-book>
|
38
|
+
<big-book>House of Leaves</big-book>
|
39
|
+
</big-books>
|
40
|
+
</book-case>
|
41
|
+
}
|
42
|
+
|
43
|
+
XML_UPCASE = %{
|
44
|
+
<BOOKCASE NAME="Jonas' Books">
|
45
|
+
<BOOKCOUNT>12</BOOKCOUNT>
|
46
|
+
<BIGBOOKS>
|
47
|
+
<BIGBOOK>GED</BIGBOOK>
|
48
|
+
<BIGBOOK>House of Leaves</BIGBOOK>
|
49
|
+
</BIGBOOKS>
|
50
|
+
</BOOKCASE>
|
51
|
+
}
|
52
|
+
|
53
|
+
class BookCase
|
54
|
+
include ROXML
|
55
|
+
|
56
|
+
xml_reader :book_count, :as => Integer, :required => true
|
57
|
+
xml_reader :big_books, :as => [], :required => true
|
58
|
+
end
|
59
|
+
|
60
|
+
class BookCaseCamelCase < BookCase
|
61
|
+
xml_convention :camelcase
|
62
|
+
end
|
63
|
+
|
64
|
+
class BookCaseUnderScore < BookCase
|
65
|
+
xml_convention :underscore
|
66
|
+
end
|
67
|
+
|
68
|
+
class BookCaseDashes < BookCase
|
69
|
+
xml_convention &:dasherize
|
70
|
+
end
|
71
|
+
|
72
|
+
class BookCaseCamelLower < BookCase
|
73
|
+
xml_convention {|val| val.camelcase(:lower) }
|
74
|
+
end
|
75
|
+
|
76
|
+
class BookCaseUpCase < BookCase
|
77
|
+
xml_convention {|val| val.gsub('_', '').upcase }
|
78
|
+
end
|
79
|
+
|
80
|
+
class InheritedBookCaseCamelCase < BookCaseCamelCase
|
81
|
+
end
|
82
|
+
|
83
|
+
class InheritedBookCaseUpCase < BookCaseUpCase
|
84
|
+
end
|
85
|
+
|
86
|
+
# Same as BookCase. Needed to keep BookCase clean for other tests
|
87
|
+
class ParentBookCaseDefault
|
88
|
+
include ROXML
|
89
|
+
|
90
|
+
xml_reader :book_count, :as => Integer, :required => true
|
91
|
+
xml_reader :big_books, :as => [], :required => true
|
92
|
+
end
|
93
|
+
|
94
|
+
class InheritedBookCaseDefault < ParentBookCaseDefault
|
95
|
+
end
|
96
|
+
|
97
|
+
class TestXMLConvention < ActiveSupport::TestCase
|
98
|
+
# TODO: Test convention applies to xml_name as well...
|
99
|
+
|
100
|
+
def test_default_convention_is_underscore
|
101
|
+
bc = BookCase.from_xml(XML_UNDERSCORE)
|
102
|
+
assert_has_book_case_info(bc)
|
103
|
+
end
|
104
|
+
|
105
|
+
[BookCaseUpCase, BookCaseCamelLower, BookCaseDashes, BookCaseUnderScore, BookCaseCamelCase].each do |klass|
|
106
|
+
define_method(:"test_xml_convention_#{klass.to_s.underscore}") do
|
107
|
+
data = :"XML_#{klass.to_s.sub('BookCase', '').upcase}"
|
108
|
+
assert_equal Proc, klass.roxml_naming_convention.class
|
109
|
+
|
110
|
+
bc = klass.from_xml(Object.const_get(data))
|
111
|
+
assert_has_book_case_info(bc)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def test_child_should_inherit_convention_if_it_doesnt_declare_one
|
116
|
+
[InheritedBookCaseUpCase, InheritedBookCaseCamelCase].each do |klass|
|
117
|
+
data = :"XML_#{klass.to_s.sub('InheritedBookCase', '').upcase}"
|
118
|
+
assert_equal Proc, klass.roxml_naming_convention.class
|
119
|
+
|
120
|
+
bc = klass.from_xml(Object.const_get(data))
|
121
|
+
assert_has_book_case_info(bc)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def test_child_should_inherit_convention_even_if_it_is_added_after_child_declaration
|
126
|
+
bc = InheritedBookCaseDefault.from_xml(XML_UNDERSCORE)
|
127
|
+
assert_has_book_case_info(bc)
|
128
|
+
|
129
|
+
ParentBookCaseDefault.class_eval do
|
130
|
+
xml_convention :dasherize
|
131
|
+
end
|
132
|
+
|
133
|
+
bc = InheritedBookCaseDefault.from_xml(XML_DASHES)
|
134
|
+
assert_has_book_case_info(bc)
|
135
|
+
assert_raise ROXML::RequiredElementMissing do
|
136
|
+
InheritedBookCaseDefault.from_xml(XML_UNDERSCORE)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def test_tag_name_should_get_convention_treatment_as_well
|
141
|
+
assert_equal "book-case-dashes", BookCaseDashes.tag_name
|
142
|
+
assert_equal "INHERITEDBOOKCASEUPCASE", InheritedBookCaseUpCase.tag_name
|
143
|
+
assert_equal "InheritedBookCaseCamelCase", InheritedBookCaseCamelCase.tag_name
|
144
|
+
end
|
145
|
+
|
146
|
+
def assert_has_book_case_info(bc)
|
147
|
+
assert_equal 12, bc.book_count
|
148
|
+
assert_equal ['GED', 'House of Leaves'], bc.big_books
|
149
|
+
end
|
150
|
+
end
|