representable 0.0.1.alpha1 → 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +58 -153
- data/lib/representable.rb +18 -42
- data/lib/representable/bindings/json_bindings.rb +69 -0
- data/lib/representable/bindings/xml_bindings.rb +152 -0
- data/lib/representable/definition.rb +1 -12
- data/lib/representable/json.rb +66 -0
- data/lib/representable/version.rb +1 -1
- data/lib/representable/xml.rb +32 -38
- data/representable.gemspec +3 -2
- data/test/bindings_test.rb +110 -0
- data/test/json_test.rb +130 -0
- data/test/{roxml_test.rb → representable_test.rb} +28 -9
- data/test/test_helper.rb +2 -0
- data/test/xml_test.rb +192 -0
- metadata +32 -105
- data/History.txt +0 -354
- data/TODO +0 -37
- data/VERSION +0 -1
- data/examples/amazon.rb +0 -35
- data/examples/current_weather.rb +0 -27
- data/examples/dashed_elements.rb +0 -20
- data/examples/library.rb +0 -40
- data/examples/posts.rb +0 -27
- data/examples/rails.rb +0 -70
- data/examples/twitter.rb +0 -37
- data/examples/xml/active_record.xml +0 -70
- data/examples/xml/amazon.xml +0 -133
- data/examples/xml/current_weather.xml +0 -89
- data/examples/xml/dashed_elements.xml +0 -52
- data/examples/xml/posts.xml +0 -23
- data/examples/xml/twitter.xml +0 -422
- data/lib/representable/references.rb +0 -153
- data/spec/definition_spec.rb +0 -495
- data/spec/examples/active_record_spec.rb +0 -41
- data/spec/examples/amazon_spec.rb +0 -54
- data/spec/examples/current_weather_spec.rb +0 -37
- data/spec/examples/dashed_elements_spec.rb +0 -20
- data/spec/examples/library_spec.rb +0 -46
- data/spec/examples/post_spec.rb +0 -24
- data/spec/examples/twitter_spec.rb +0 -32
- data/spec/roxml_integration_test.rb +0 -289
- data/spec/roxml_spec.rb +0 -372
- data/spec/shared_specs.rb +0 -15
- data/spec/spec_helper.rb +0 -5
- data/spec/support/libxml.rb +0 -3
- data/spec/support/nokogiri.rb +0 -3
- data/spec/xml/array_spec.rb +0 -36
- data/spec/xml/attributes_spec.rb +0 -71
- data/spec/xml/encoding_spec.rb +0 -53
- data/spec/xml/namespace_spec.rb +0 -270
- data/spec/xml/namespaces_spec.rb +0 -67
- data/spec/xml/object_spec.rb +0 -82
- data/spec/xml/parser_spec.rb +0 -21
- data/spec/xml/text_spec.rb +0 -71
- data/test/fixtures/book_malformed.xml +0 -5
- data/test/fixtures/book_pair.xml +0 -8
- data/test/fixtures/book_text_with_attribute.xml +0 -5
- data/test/fixtures/book_valid.xml +0 -5
- data/test/fixtures/book_with_authors.xml +0 -7
- data/test/fixtures/book_with_contributions.xml +0 -9
- data/test/fixtures/book_with_contributors.xml +0 -7
- data/test/fixtures/book_with_contributors_attrs.xml +0 -7
- data/test/fixtures/book_with_default_namespace.xml +0 -9
- data/test/fixtures/book_with_depth.xml +0 -6
- data/test/fixtures/book_with_octal_pages.xml +0 -4
- data/test/fixtures/book_with_publisher.xml +0 -7
- data/test/fixtures/book_with_wrapped_attr.xml +0 -3
- data/test/fixtures/dictionary_of_attr_name_clashes.xml +0 -8
- data/test/fixtures/dictionary_of_attrs.xml +0 -6
- data/test/fixtures/dictionary_of_guarded_names.xml +0 -6
- data/test/fixtures/dictionary_of_mixeds.xml +0 -4
- data/test/fixtures/dictionary_of_name_clashes.xml +0 -10
- data/test/fixtures/dictionary_of_names.xml +0 -4
- data/test/fixtures/dictionary_of_texts.xml +0 -10
- data/test/fixtures/library.xml +0 -30
- data/test/fixtures/library_uppercase.xml +0 -30
- data/test/fixtures/muffins.xml +0 -3
- data/test/fixtures/nameless_ageless_youth.xml +0 -2
- data/test/fixtures/node_with_attr_name_conflicts.xml +0 -1
- data/test/fixtures/node_with_name_conflicts.xml +0 -4
- data/test/fixtures/numerology.xml +0 -4
- data/test/fixtures/person.xml +0 -1
- data/test/fixtures/person_with_guarded_mothers.xml +0 -13
- data/test/fixtures/person_with_mothers.xml +0 -10
- data/test/mocks/dictionaries.rb +0 -57
- data/test/mocks/mocks.rb +0 -279
- data/test/support/fixtures.rb +0 -11
- data/test/unit/definition_test.rb +0 -235
- data/test/unit/deprecations_test.rb +0 -24
- data/test/unit/to_xml_test.rb +0 -81
- data/test/unit/xml_attribute_test.rb +0 -39
- data/test/unit/xml_block_test.rb +0 -81
- data/test/unit/xml_bool_test.rb +0 -122
- data/test/unit/xml_convention_test.rb +0 -150
- data/test/unit/xml_hash_test.rb +0 -115
- data/test/unit/xml_initialize_test.rb +0 -49
- data/test/unit/xml_name_test.rb +0 -141
- data/test/unit/xml_namespace_test.rb +0 -31
- data/test/unit/xml_object_test.rb +0 -206
- data/test/unit/xml_required_test.rb +0 -94
- data/test/unit/xml_text_test.rb +0 -71
- data/website/index.html +0 -98
@@ -1,153 +0,0 @@
|
|
1
|
-
module Representable
|
2
|
-
class RequiredElementMissing < Exception # :nodoc:
|
3
|
-
end
|
4
|
-
|
5
|
-
# Internal base class that represents an XML - Class binding.
|
6
|
-
class XMLRef
|
7
|
-
attr_reader :definition
|
8
|
-
delegate :required?, :array?, :accessor, :wrapper, :name, :to => :definition
|
9
|
-
|
10
|
-
def initialize(definition)
|
11
|
-
@definition = definition
|
12
|
-
end
|
13
|
-
|
14
|
-
def value_in(xml)
|
15
|
-
xml = Nokogiri::XML::Node.from(xml) or return default
|
16
|
-
|
17
|
-
value_from_node(xml) or default
|
18
|
-
end
|
19
|
-
|
20
|
-
private
|
21
|
-
def default
|
22
|
-
""
|
23
|
-
end
|
24
|
-
|
25
|
-
def xpath
|
26
|
-
name
|
27
|
-
end
|
28
|
-
|
29
|
-
def wrap(xml, opts = {:always_create => false})
|
30
|
-
wrap_with = @auto_vals ? auto_wrapper : wrapper
|
31
|
-
|
32
|
-
return xml if !wrap_with || xml.name == wrap_with
|
33
|
-
if !opts[:always_create] && (child = xml.children.find {|c| c.name == wrap_with })
|
34
|
-
return child
|
35
|
-
end
|
36
|
-
xml.add_node(wrap_with.to_s)
|
37
|
-
end
|
38
|
-
|
39
|
-
def collect_for(xml)
|
40
|
-
nodes = xml.search("./#{xpath}")
|
41
|
-
vals = nodes.collect { |node| yield node }
|
42
|
-
|
43
|
-
array? ? vals : vals.first
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
# Represents a tag attribute.
|
48
|
-
class XMLAttributeRef < XMLRef
|
49
|
-
# Updates the attribute in the given XML block to
|
50
|
-
# the value provided.
|
51
|
-
def update_xml(xml, values)
|
52
|
-
wrap(xml).tap do |xml|
|
53
|
-
xml[name] = values.to_s
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
private
|
58
|
-
def value_from_node(xml)
|
59
|
-
xml[name]
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
# Represents text content in a tag.
|
64
|
-
class XMLTextRef < XMLRef
|
65
|
-
delegate :cdata?, :content?, :name?, :to => :definition
|
66
|
-
|
67
|
-
# Updates the text in the given _xml_ block to
|
68
|
-
# the _value_ provided.
|
69
|
-
def update_xml(xml, value)
|
70
|
-
wrap(xml).tap do |xml|
|
71
|
-
if content?
|
72
|
-
add(xml, value)
|
73
|
-
elsif name?
|
74
|
-
xml.name = value
|
75
|
-
elsif array?
|
76
|
-
value.each do |v|
|
77
|
-
add(xml.add_node(name), v)
|
78
|
-
end
|
79
|
-
else
|
80
|
-
add(xml.add_node(name), value)
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
private
|
86
|
-
def value_from_node(xml)
|
87
|
-
collect_for(xml) do |node|
|
88
|
-
node.content
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
def add(dest, value)
|
93
|
-
if cdata?
|
94
|
-
dest.add_child(Nokogiri::XML::CDATA.new(dest.document, content))
|
95
|
-
else
|
96
|
-
dest.content = value.to_s
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
class XMLNameSpaceRef < XMLRef
|
102
|
-
private
|
103
|
-
def value_from_node(xml)
|
104
|
-
xml.namespace.prefix
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
# Represents a tag with object binding.
|
109
|
-
class XMLObjectRef < XMLTextRef
|
110
|
-
delegate :sought_type, :to => :definition
|
111
|
-
|
112
|
-
# Adds the ref's markup to +xml+.
|
113
|
-
def update_xml(xml, value)
|
114
|
-
wrap(xml).tap do |xml|
|
115
|
-
if array?
|
116
|
-
update_xml_for_collection(xml, value)
|
117
|
-
else
|
118
|
-
update_xml_for_entity(xml, value)
|
119
|
-
end
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
private
|
124
|
-
def default
|
125
|
-
[]
|
126
|
-
end
|
127
|
-
|
128
|
-
def serialize(object)
|
129
|
-
object.to_xml
|
130
|
-
end
|
131
|
-
|
132
|
-
def deserialize(node_class, xml)
|
133
|
-
node_class.from_xml(xml)
|
134
|
-
end
|
135
|
-
|
136
|
-
# Deserializes the ref's element from +xml+.
|
137
|
-
def value_from_node(xml)
|
138
|
-
collect_for(xml) do |node|
|
139
|
-
deserialize(sought_type, node)
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
|
-
def update_xml_for_collection(xml, collection)
|
144
|
-
collection.each do |item|
|
145
|
-
update_xml_for_entity(xml, item)
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
def update_xml_for_entity(xml, entity)
|
150
|
-
xml.add_child(serialize(entity))
|
151
|
-
end
|
152
|
-
end
|
153
|
-
end
|
data/spec/definition_spec.rb
DELETED
@@ -1,495 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
require_relative './spec_helper'
|
3
|
-
|
4
|
-
describe ROXML::Definition do
|
5
|
-
describe "#name_explicit?" do
|
6
|
-
it "should indicate whether from option is present" do
|
7
|
-
ROXML::Definition.new(:element, :from => 'somewhere').name_explicit?.should be_true
|
8
|
-
ROXML::Definition.new(:element).name_explicit?.should be_false
|
9
|
-
end
|
10
|
-
|
11
|
-
it "should not consider name proxies as explicit" do
|
12
|
-
ROXML::Definition.new(:element, :from => :attr).name_explicit?.should be_false
|
13
|
-
ROXML::Definition.new(:element, :from => :content).name_explicit?.should be_false
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
shared_examples_for "DateTime reference" do
|
18
|
-
it "should return nil on empty string" do
|
19
|
-
@subject.blocks.first.call(" ").should be_nil
|
20
|
-
end
|
21
|
-
|
22
|
-
it "should return a time version of the string" do
|
23
|
-
@subject.blocks.first.call("12:05pm, September 3rd, 1970").to_s == "1970-09-03T12:05:00+00:00"
|
24
|
-
end
|
25
|
-
|
26
|
-
context "when passed an array of values" do
|
27
|
-
it "should timify all of them" do
|
28
|
-
@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"]
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
shared_examples_for "Date reference" do
|
34
|
-
it "should return nil on empty string" do
|
35
|
-
@subject.blocks.first.call(" ").should be_nil
|
36
|
-
end
|
37
|
-
|
38
|
-
it "should return a time version of the string" do
|
39
|
-
@subject.blocks.first.call("September 3rd, 1970").to_s == "1970-09-03"
|
40
|
-
end
|
41
|
-
|
42
|
-
context "when passed an array of values" do
|
43
|
-
it "should timify all of them" do
|
44
|
-
@subject.blocks.first.call(["September 3rd, 1970", "1776-07-04"]).map(&:to_s).should == ["1970-09-03", "1776-07-04"]
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
it "should unescape xml entities" do
|
50
|
-
ROXML::Definition.new(:questions, :as => []).to_ref(RoxmlObject.new).value_in(%{
|
51
|
-
<xml>
|
52
|
-
<question>"Wickard & Filburn" ></question>
|
53
|
-
<question> < McCulloch & Maryland?</question>
|
54
|
-
</xml>
|
55
|
-
}).should == ["\"Wickard & Filburn\" >", " < McCulloch & Maryland?"]
|
56
|
-
end
|
57
|
-
|
58
|
-
it "should unescape utf characters in xml" do
|
59
|
-
ROXML::Definition.new(:questions, :as => []).to_ref(RoxmlObject.new).value_in(%{
|
60
|
-
<xml>
|
61
|
-
<question>ROXML\342\204\242</question>
|
62
|
-
</xml>
|
63
|
-
}).should == ["ROXML™"]
|
64
|
-
end
|
65
|
-
|
66
|
-
describe "attr name" do
|
67
|
-
context "when ending with '_at'" do
|
68
|
-
context "and without an :as argument" do
|
69
|
-
before(:all) do
|
70
|
-
@subject = ROXML::Definition.new(:time_at)
|
71
|
-
end
|
72
|
-
it_should_behave_like "DateTime reference"
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
context "when ending with '_on'" do
|
77
|
-
context "and without an :as argument" do
|
78
|
-
before(:all) do
|
79
|
-
@subject = ROXML::Definition.new(:created_on)
|
80
|
-
end
|
81
|
-
it_should_behave_like "Date reference"
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
describe ":as" do
|
87
|
-
describe "=> []" do
|
88
|
-
it "should means array of texts" do
|
89
|
-
opts = ROXML::Definition.new(:authors, :as => [])
|
90
|
-
opts.array?.should be_true
|
91
|
-
opts.sought_type.should == :text
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
describe "=> RoxmlClass" do
|
96
|
-
class RoxmlClass
|
97
|
-
include ROXML
|
98
|
-
end
|
99
|
-
|
100
|
-
it "should store type" do
|
101
|
-
opts = ROXML::Definition.new(:name, :as => RoxmlClass)
|
102
|
-
opts.sought_type.should == RoxmlClass
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
describe "=> NonRoxmlClassWithFromXmlDefined" do
|
107
|
-
class OctalInteger
|
108
|
-
def self.from_xml(val)
|
109
|
-
new(Integer(val.content))
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
it "should accept type" do
|
114
|
-
opts = ROXML::Definition.new(:name, :as => OctalInteger)
|
115
|
-
opts.sought_type.should == OctalInteger
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
describe "=> NonRoxmlClass" do
|
120
|
-
it "should fail with a warning" do
|
121
|
-
proc { ROXML::Definition.new(:authors, :as => Module) }.should raise_error(ArgumentError)
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
describe "=> [NonRoxmlClass]" do
|
126
|
-
it "should raise" do
|
127
|
-
proc { ROXML::Definition.new(:authors, :as => [Module]) }.should raise_error(ArgumentError)
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
describe "=> {}" do
|
132
|
-
shared_examples_for "hash options declaration" do
|
133
|
-
it "should represent a hash" do
|
134
|
-
@opts.hash?.should be_true
|
135
|
-
end
|
136
|
-
|
137
|
-
it "should have hash definition" do
|
138
|
-
{@opts.hash.key.sought_type => @opts.hash.key.name}.should == @hash_args[:key]
|
139
|
-
{@opts.hash.value.sought_type => @opts.hash.value.name}.should == @hash_args[:value]
|
140
|
-
end
|
141
|
-
|
142
|
-
it "should not represent an array" do
|
143
|
-
@opts.array?.should be_false
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
describe "hash with attr key and text val" do
|
148
|
-
before do
|
149
|
-
@opts = ROXML::Definition.new(:attributes, :as => {:key => '@name',
|
150
|
-
:value => 'value'})
|
151
|
-
@hash_args = {:key => {:attr => 'name'},
|
152
|
-
:value => {:text => 'value'}}
|
153
|
-
end
|
154
|
-
|
155
|
-
it_should_behave_like "hash options declaration"
|
156
|
-
end
|
157
|
-
|
158
|
-
describe "hash with String class for type" do
|
159
|
-
before do
|
160
|
-
@opts = ROXML::Definition.new(:attributes, :as => {:key => 'name',
|
161
|
-
:value => 'value'})
|
162
|
-
@hash_args = {:key => {:text => 'name'}, :value => {:text => 'value'}}
|
163
|
-
end
|
164
|
-
|
165
|
-
it_should_behave_like "hash options declaration"
|
166
|
-
end
|
167
|
-
|
168
|
-
describe "hash with attr key and content val" do
|
169
|
-
before do
|
170
|
-
@opts = ROXML::Definition.new(:attributes, :as => {:key => '@name',
|
171
|
-
:value => :content})
|
172
|
-
@hash_args = {:key => {:attr => 'name'}, :value => {:text => '.'}}
|
173
|
-
end
|
174
|
-
|
175
|
-
it_should_behave_like "hash options declaration"
|
176
|
-
end
|
177
|
-
|
178
|
-
describe "hash with names as keys and content vals" do
|
179
|
-
before do
|
180
|
-
@opts = ROXML::Definition.new(:attributes, :as => {:key => :name,
|
181
|
-
:value => :content})
|
182
|
-
@hash_args = {:key => {:text => '*'}, :value => {:text => '.'}}
|
183
|
-
end
|
184
|
-
|
185
|
-
it_should_behave_like "hash options declaration"
|
186
|
-
end
|
187
|
-
end
|
188
|
-
|
189
|
-
describe "for block shorthand" do
|
190
|
-
describe "in literal array" do
|
191
|
-
before do
|
192
|
-
@opts = ROXML::Definition.new(:intarray, :as => [Integer])
|
193
|
-
end
|
194
|
-
|
195
|
-
it "should be detected as array reference" do
|
196
|
-
@opts.array?.should be_true
|
197
|
-
end
|
198
|
-
|
199
|
-
it "should be normal otherwise" do
|
200
|
-
@opts.sought_type.should == :text
|
201
|
-
@opts.blocks.size.should == 1
|
202
|
-
end
|
203
|
-
end
|
204
|
-
|
205
|
-
it "should have no blocks without a shorthand" do
|
206
|
-
ROXML::Definition.new(:count).blocks.should be_empty
|
207
|
-
end
|
208
|
-
|
209
|
-
it "should raise on unknown :as" do
|
210
|
-
proc { ROXML::Definition.new(:count, :as => :bogus) }.should raise_error(ArgumentError)
|
211
|
-
proc { ROXML::Definition.new(:count, :as => :foat) }.should raise_error(ArgumentError)
|
212
|
-
end
|
213
|
-
|
214
|
-
shared_examples_for "block shorthand type declaration" do
|
215
|
-
it "should translate nil to nil" do
|
216
|
-
@definition.blocks.first.call(nil).should be_nil
|
217
|
-
end
|
218
|
-
|
219
|
-
it "should translate empty strings to nil" do
|
220
|
-
@definition.blocks.first.call("").should be_nil
|
221
|
-
@definition.blocks.first.call(" ").should be_nil
|
222
|
-
end
|
223
|
-
end
|
224
|
-
|
225
|
-
describe "Integer" do
|
226
|
-
before do
|
227
|
-
@definition = ROXML::Definition.new(:intvalue, :as => Integer)
|
228
|
-
end
|
229
|
-
|
230
|
-
it_should_behave_like "block shorthand type declaration"
|
231
|
-
|
232
|
-
it "should translate text to integers" do
|
233
|
-
@definition.blocks.first['3'].should == 3
|
234
|
-
@definition.blocks.first['792'].should == 792
|
235
|
-
end
|
236
|
-
|
237
|
-
it "should raise on non-integer values" do
|
238
|
-
proc { @definition.blocks.first['08'] }.should raise_error(ArgumentError)
|
239
|
-
proc { @definition.blocks.first['793.12'] }.should raise_error(ArgumentError)
|
240
|
-
proc { @definition.blocks.first['junk 11'] }.should raise_error(ArgumentError)
|
241
|
-
proc { @definition.blocks.first['11sttf'] }.should raise_error(ArgumentError)
|
242
|
-
end
|
243
|
-
|
244
|
-
context "when passed an array" do
|
245
|
-
it "should translate the array elements to integer" do
|
246
|
-
@definition.blocks.first.call(["792", "12", "328"]).should == [792, 12, 328]
|
247
|
-
end
|
248
|
-
end
|
249
|
-
end
|
250
|
-
|
251
|
-
describe "Float" do
|
252
|
-
before do
|
253
|
-
@definition = ROXML::Definition.new(:floatvalue, :as => Float)
|
254
|
-
end
|
255
|
-
|
256
|
-
it_should_behave_like "block shorthand type declaration"
|
257
|
-
|
258
|
-
it "should translate text to float" do
|
259
|
-
@definition.blocks.first['3'].should == 3.0
|
260
|
-
@definition.blocks.first['12.7'].should == 12.7
|
261
|
-
end
|
262
|
-
|
263
|
-
it "should raise on non-float values" do
|
264
|
-
proc { @definition.blocks.first['junk 11.3'] }.should raise_error(ArgumentError)
|
265
|
-
proc { @definition.blocks.first['11.1sttf'] }.should raise_error(ArgumentError)
|
266
|
-
end
|
267
|
-
|
268
|
-
context "when passed an array" do
|
269
|
-
it "should translate the array elements to integer" do
|
270
|
-
@definition.blocks.first.call(["792.13", "240", "3.14"]).should == [792.13, 240.0, 3.14]
|
271
|
-
end
|
272
|
-
end
|
273
|
-
end
|
274
|
-
|
275
|
-
describe "BigDecimal" do
|
276
|
-
before do
|
277
|
-
@definition = ROXML::Definition.new(:decimalvalue, :as => BigDecimal)
|
278
|
-
end
|
279
|
-
|
280
|
-
it_should_behave_like "block shorthand type declaration"
|
281
|
-
|
282
|
-
it "should translate text to decimal numbers" do
|
283
|
-
@definition.blocks.first['3'].should == BigDecimal.new("3.0")
|
284
|
-
@definition.blocks.first['0.3'].should == BigDecimal.new("0.3")
|
285
|
-
end
|
286
|
-
|
287
|
-
it "should extract what it can, and fall back to 0" do
|
288
|
-
@definition.blocks.first['junk 11'].should eql(BigDecimal.new("0"))
|
289
|
-
@definition.blocks.first['11sttf'].should eql(BigDecimal.new("11.0"))
|
290
|
-
end
|
291
|
-
|
292
|
-
context "when passed an array" do
|
293
|
-
it "should translate the array elements to integer" do
|
294
|
-
@definition.blocks.first.call(["12.1", "328.2"]).should == [BigDecimal.new("12.1"), BigDecimal.new("328.2")]
|
295
|
-
end
|
296
|
-
end
|
297
|
-
end
|
298
|
-
|
299
|
-
describe "Fixnum" do
|
300
|
-
before do
|
301
|
-
@definition = ROXML::Definition.new(:fixnumvalue, :as => Fixnum)
|
302
|
-
end
|
303
|
-
|
304
|
-
it_should_behave_like "block shorthand type declaration"
|
305
|
-
|
306
|
-
it "should translate text to integers" do
|
307
|
-
@definition.blocks.first['3'].should == 3
|
308
|
-
@definition.blocks.first['792'].should == 792
|
309
|
-
@definition.blocks.first['08'].should == 8
|
310
|
-
@definition.blocks.first['279.23'].should == 279
|
311
|
-
end
|
312
|
-
|
313
|
-
it "should extract whatever is possible and fall back to 0" do
|
314
|
-
@definition.blocks.first['junk 11'].should eql(0)
|
315
|
-
@definition.blocks.first['.?sttf'].should eql(0)
|
316
|
-
@definition.blocks.first['11sttf'].should eql(11)
|
317
|
-
end
|
318
|
-
|
319
|
-
context "when passed an array" do
|
320
|
-
it "should translate the array elements to integer" do
|
321
|
-
@definition.blocks.first.call(["792", "12", "328"]).should == [792, 12, 328]
|
322
|
-
end
|
323
|
-
end
|
324
|
-
end
|
325
|
-
|
326
|
-
describe ":bool" do
|
327
|
-
it "should boolify individual values" do
|
328
|
-
ROXML::Definition.new(:floatvalue, :as => :bool).blocks.first.call("1").should be_true
|
329
|
-
ROXML::Definition.new(:floatvalue, :as => :bool).blocks.first.call("True").should be_true
|
330
|
-
ROXML::Definition.new(:floatvalue, :as => :bool).blocks.first.call("Yes").should be_true
|
331
|
-
end
|
332
|
-
|
333
|
-
context "when an array is passed in" do
|
334
|
-
it "should boolify arrays of values" do
|
335
|
-
ROXML::Definition.new(:floatvalue, :as => :bool).blocks.first.call("0").should be_false
|
336
|
-
ROXML::Definition.new(:floatvalue, :as => :bool).blocks.first.call("false").should be_false
|
337
|
-
ROXML::Definition.new(:floatvalue, :as => :bool).blocks.first.call("nO").should be_false
|
338
|
-
end
|
339
|
-
end
|
340
|
-
|
341
|
-
context "when no value is detected" do
|
342
|
-
it "should return nil" do
|
343
|
-
ROXML::Definition.new(:floatvalue, :as => :bool).blocks.first.call("junk").should be_nil
|
344
|
-
end
|
345
|
-
|
346
|
-
context "when a literal block is available" do
|
347
|
-
it "should pass the value itself to the block"
|
348
|
-
end
|
349
|
-
end
|
350
|
-
end
|
351
|
-
|
352
|
-
describe "Time" do
|
353
|
-
it "should return nil on empty string" do
|
354
|
-
ROXML::Definition.new(:floatvalue, :as => Time).blocks.first.call(" ").should be_nil
|
355
|
-
end
|
356
|
-
|
357
|
-
it "should return a time version of the string" do
|
358
|
-
ROXML::Definition.new(:datevalue, :as => Time).blocks.first.call("12:31am").min.should == 31
|
359
|
-
end
|
360
|
-
|
361
|
-
context "when passed an array of values" do
|
362
|
-
it "should timify all of them" do
|
363
|
-
ROXML::Definition.new(:datevalue, :as => Time).blocks.first.call(["12:31am", "3:00pm", "11:59pm"]).map(&:min).should == [31, 0, 59]
|
364
|
-
end
|
365
|
-
end
|
366
|
-
end
|
367
|
-
|
368
|
-
describe "Date" do
|
369
|
-
before do
|
370
|
-
@subject = ROXML::Definition.new(:datevalue, :as => Date)
|
371
|
-
end
|
372
|
-
it_should_behave_like "Date reference"
|
373
|
-
end
|
374
|
-
|
375
|
-
describe "DateTime" do
|
376
|
-
before do
|
377
|
-
@subject = ROXML::Definition.new(:datevalue, :as => DateTime)
|
378
|
-
end
|
379
|
-
it_should_behave_like "DateTime reference"
|
380
|
-
end
|
381
|
-
|
382
|
-
it "should prohibit multiple shorthands" do
|
383
|
-
proc { ROXML::Definition.new(:count, :as => [Float, Integer]) }.should raise_error(ArgumentError)
|
384
|
-
end
|
385
|
-
|
386
|
-
it "should stack block shorthands with explicit blocks" do
|
387
|
-
ROXML::Definition.new(:count, :as => Integer) {|val| val.to_i }.blocks.size.should == 2
|
388
|
-
ROXML::Definition.new(:count, :as => Float) {|val| val.object_id }.blocks.size.should == 2
|
389
|
-
end
|
390
|
-
end
|
391
|
-
end
|
392
|
-
|
393
|
-
describe ":from" do
|
394
|
-
shared_examples_for "attribute reference" do
|
395
|
-
it "should be interpreted as :attr" do
|
396
|
-
@opts.sought_type.should == :attr
|
397
|
-
end
|
398
|
-
|
399
|
-
it "should strip '@' from name" do
|
400
|
-
@opts.name.should == 'attr_name'
|
401
|
-
end
|
402
|
-
|
403
|
-
it "should unescape xml entities" do
|
404
|
-
@opts.to_ref(RoxmlObject.new).value_in(%{
|
405
|
-
<question attr_name=""Wickard & Filburn" > / < McCulloch & Marryland?" />
|
406
|
-
}).should == "\"Wickard & Filburn\" > / < McCulloch & Marryland?"
|
407
|
-
end
|
408
|
-
end
|
409
|
-
|
410
|
-
context ":attr" do
|
411
|
-
before do
|
412
|
-
@opts = ROXML::Definition.new(:attr_name, :from => :attr)
|
413
|
-
end
|
414
|
-
|
415
|
-
it_should_behave_like "attribute reference"
|
416
|
-
end
|
417
|
-
|
418
|
-
context "@attribute_name" do
|
419
|
-
before do
|
420
|
-
@opts = ROXML::Definition.new(:attr_name, :from => '@attr_name')
|
421
|
-
end
|
422
|
-
|
423
|
-
it_should_behave_like "attribute reference"
|
424
|
-
end
|
425
|
-
|
426
|
-
describe ":content" do
|
427
|
-
it "should be recognized" do
|
428
|
-
ROXML::Definition.new(:author).content?.should be_false
|
429
|
-
ROXML::Definition.new(:author, :from => :content).content?.should == true
|
430
|
-
end
|
431
|
-
|
432
|
-
it "should be equivalent to :from => '.'" do
|
433
|
-
ROXML::Definition.new(:author, :from => '.').content?.should == true
|
434
|
-
end
|
435
|
-
end
|
436
|
-
end
|
437
|
-
|
438
|
-
describe ":in" do
|
439
|
-
context "as xpath" do
|
440
|
-
it "should pass through as wrapper" do
|
441
|
-
ROXML::Definition.new(:manufacturer, :in => './').wrapper.should == './'
|
442
|
-
end
|
443
|
-
end
|
444
|
-
|
445
|
-
context "as xpath" do
|
446
|
-
it "should pass through as wrapper" do
|
447
|
-
ROXML::Definition.new(:manufacturer, :in => 'wrapper').wrapper.should == 'wrapper'
|
448
|
-
end
|
449
|
-
end
|
450
|
-
end
|
451
|
-
|
452
|
-
describe "options" do
|
453
|
-
|
454
|
-
shared_examples_for "boolean option" do
|
455
|
-
it "should be recognized" do
|
456
|
-
ROXML::Definition.new(:author, :from => :content, @option => true).respond_to?(:"#{@option}?")
|
457
|
-
ROXML::Definition.new(:author, :from => :content, @option => true).send(:"#{@option}?").should be_true
|
458
|
-
ROXML::Definition.new(:author, :from => :content, @option => false).send(:"#{@option}?").should be_false
|
459
|
-
end
|
460
|
-
|
461
|
-
it "should default to false" do
|
462
|
-
ROXML::Definition.new(:author, :from => :content).send(:"#{@option}?").should be_false
|
463
|
-
end
|
464
|
-
end
|
465
|
-
|
466
|
-
describe ":required" do
|
467
|
-
before do
|
468
|
-
@option = :required
|
469
|
-
end
|
470
|
-
|
471
|
-
it_should_behave_like "boolean option"
|
472
|
-
|
473
|
-
it "should not be allowed together with :else" do
|
474
|
-
proc { ROXML::Definition.new(:author, :from => :content, :required => true, :else => 'Johnny') }.should raise_error(ArgumentError)
|
475
|
-
proc { ROXML::Definition.new(:author, :from => :content, :required => false, :else => 'Johnny') }.should_not raise_error
|
476
|
-
end
|
477
|
-
end
|
478
|
-
|
479
|
-
describe ":frozen" do
|
480
|
-
before do
|
481
|
-
@option = :frozen
|
482
|
-
end
|
483
|
-
|
484
|
-
it_should_behave_like "boolean option"
|
485
|
-
end
|
486
|
-
|
487
|
-
describe ":cdata" do
|
488
|
-
before do
|
489
|
-
@option = :cdata
|
490
|
-
end
|
491
|
-
|
492
|
-
it_should_behave_like "boolean option"
|
493
|
-
end
|
494
|
-
end
|
495
|
-
end
|