representative 0.2.5 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Rakefile +4 -9
- data/lib/representative/abstract_xml.rb +119 -0
- data/lib/representative/json.rb +14 -2
- data/lib/representative/nokogiri.rb +61 -0
- data/lib/representative/tilt_integration.rb +56 -0
- data/lib/representative/version.rb +1 -1
- data/lib/representative/xml.rb +10 -116
- data/spec/representative/json_spec.rb +49 -0
- data/spec/representative/nokogiri_spec.rb +74 -0
- data/spec/representative/tilt_integration_spec.rb +136 -0
- data/spec/representative/xml_behaviour.rb +270 -0
- data/spec/representative/xml_spec.rb +3 -264
- data/spec/spec_helper.rb +0 -3
- metadata +65 -41
@@ -53,6 +53,38 @@ describe Representative::Json do
|
|
53
53
|
end
|
54
54
|
|
55
55
|
end
|
56
|
+
|
57
|
+
describe "with attributes" do
|
58
|
+
|
59
|
+
describe "and a block" do
|
60
|
+
|
61
|
+
it "generates labelled fields for the attributes" do
|
62
|
+
@book = OpenStruct.new(:lang => "fr", :title => "En Edge")
|
63
|
+
r.element :book, @book, :lang => :lang do
|
64
|
+
r.element :title
|
65
|
+
end
|
66
|
+
resulting_json.should == undent(<<-JSON)
|
67
|
+
{
|
68
|
+
"@lang": "fr",
|
69
|
+
"title": "En Edge"
|
70
|
+
}
|
71
|
+
JSON
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
describe "and an explicit value" do
|
77
|
+
|
78
|
+
it "ignores the attributes" do
|
79
|
+
r.element :review, "Blah de blah", :lang => "fr"
|
80
|
+
resulting_json.should == undent(<<-JSON)
|
81
|
+
"Blah de blah"
|
82
|
+
JSON
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
56
88
|
|
57
89
|
describe "without an explicit value" do
|
58
90
|
|
@@ -199,6 +231,23 @@ describe Representative::Json do
|
|
199
231
|
|
200
232
|
end
|
201
233
|
|
234
|
+
describe "#attribute" do
|
235
|
+
|
236
|
+
it "generates labelled values, with a label prefix" do
|
237
|
+
r.element :author, Object.new do
|
238
|
+
r.attribute :href, "http://example.com/authors/1"
|
239
|
+
r.element :name, "Fred"
|
240
|
+
end
|
241
|
+
resulting_json.should == undent(<<-JSON)
|
242
|
+
{
|
243
|
+
"@href": "http://example.com/authors/1",
|
244
|
+
"name": "Fred"
|
245
|
+
}
|
246
|
+
JSON
|
247
|
+
end
|
248
|
+
|
249
|
+
end
|
250
|
+
|
202
251
|
describe "#comment" do
|
203
252
|
|
204
253
|
it "inserts a comment" do
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require "nokogiri"
|
4
|
+
require "representative/nokogiri"
|
5
|
+
require "representative/xml_behaviour"
|
6
|
+
|
7
|
+
describe Representative::Nokogiri do
|
8
|
+
|
9
|
+
def r
|
10
|
+
@representative ||= Representative::Nokogiri.new(@subject)
|
11
|
+
end
|
12
|
+
|
13
|
+
def resulting_xml
|
14
|
+
r.to_xml(:save_with => Nokogiri::XML::Node::SaveOptions::NO_DECLARATION).rstrip
|
15
|
+
end
|
16
|
+
|
17
|
+
it_should_behave_like "an XML Representative"
|
18
|
+
|
19
|
+
describe "for some 'subject'" do
|
20
|
+
|
21
|
+
before do
|
22
|
+
@subject = OpenStruct.new(:name => "Fred", :width => 200, :vehicle => OpenStruct.new(:year => "1959", :make => "Chevrolet"))
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "#attribute" do
|
26
|
+
|
27
|
+
describe "without a value argument" do
|
28
|
+
it "extracts the named field of the subject" do
|
29
|
+
r.element :person, @subject do
|
30
|
+
r.attribute :name
|
31
|
+
end
|
32
|
+
resulting_xml.should == %(<person name="Fred"/>)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "with an explicit value" do
|
37
|
+
it "attaches an attribute to the current element" do
|
38
|
+
r.element :person, @subject do
|
39
|
+
r.attribute :lang, "fr"
|
40
|
+
end
|
41
|
+
resulting_xml.should == %(<person lang="fr"/>)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "with a value that supports #to_proc" do
|
46
|
+
it "calls the Proc on the subject to generate attribute value" do
|
47
|
+
r.element :person, @subject do
|
48
|
+
r.attribute :name, lambda { |person| person.name.reverse }
|
49
|
+
end
|
50
|
+
resulting_xml.should == %(<person name="derF"/>)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
it "dasherizes the attribute name" do
|
55
|
+
r.element :name do
|
56
|
+
r.attribute :sourced_from, "phonebook"
|
57
|
+
end
|
58
|
+
resulting_xml.should == %(<name sourced-from="phonebook"/>)
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "with value nil" do
|
62
|
+
it "omits the attribute" do
|
63
|
+
r.element :person, @subject do
|
64
|
+
r.attribute :name, nil
|
65
|
+
end
|
66
|
+
resulting_xml.should == %(<person/>)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require "ostruct"
|
4
|
+
require "representative/tilt_integration"
|
5
|
+
|
6
|
+
describe Representative::Tilt do
|
7
|
+
|
8
|
+
def with_template(file_name, content)
|
9
|
+
@template = Tilt.new(file_name, 1) { content }
|
10
|
+
end
|
11
|
+
|
12
|
+
def render(*args, &block)
|
13
|
+
@output = @template.render(*args, &block)
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "XML template" do
|
17
|
+
|
18
|
+
def resulting_xml
|
19
|
+
@output.sub(/^<\?xml.*\n/, '')
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "#render" do
|
23
|
+
|
24
|
+
it "generates XML" do
|
25
|
+
with_template("whatever.xml.rep", <<-RUBY)
|
26
|
+
r.element :foo, "bar"
|
27
|
+
RUBY
|
28
|
+
render
|
29
|
+
resulting_xml.should == %{<foo>bar</foo>\n}
|
30
|
+
end
|
31
|
+
|
32
|
+
it "provides access to scope" do
|
33
|
+
|
34
|
+
with_template("whatever.xml.rep", <<-RUBY)
|
35
|
+
r.element :author, @mike do
|
36
|
+
r.element :name
|
37
|
+
end
|
38
|
+
RUBY
|
39
|
+
|
40
|
+
scope = Object.new
|
41
|
+
scope.instance_eval do
|
42
|
+
@mike = OpenStruct.new(:name => "Mike")
|
43
|
+
end
|
44
|
+
render(scope)
|
45
|
+
|
46
|
+
resulting_xml.should == undent(<<-XML)
|
47
|
+
<author>
|
48
|
+
<name>Mike</name>
|
49
|
+
</author>
|
50
|
+
XML
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
it "provides access to local variables" do
|
55
|
+
|
56
|
+
with_template("whatever.xml.rep", <<-RUBY)
|
57
|
+
r.element :author, author do
|
58
|
+
r.element :name
|
59
|
+
end
|
60
|
+
RUBY
|
61
|
+
|
62
|
+
render(Object.new, {:author => OpenStruct.new(:name => "Mike")})
|
63
|
+
|
64
|
+
resulting_xml.should == undent(<<-XML)
|
65
|
+
<author>
|
66
|
+
<name>Mike</name>
|
67
|
+
</author>
|
68
|
+
XML
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
describe "JSON template" do
|
77
|
+
|
78
|
+
def resulting_json
|
79
|
+
@output.sub(/^<\?xml.*\n/, '')
|
80
|
+
end
|
81
|
+
|
82
|
+
describe "#render" do
|
83
|
+
|
84
|
+
it "generates JSON" do
|
85
|
+
with_template("whatever.json.rep", <<-RUBY)
|
86
|
+
r.element :foo, "bar"
|
87
|
+
RUBY
|
88
|
+
render
|
89
|
+
resulting_json.should == %{"bar"\n}
|
90
|
+
end
|
91
|
+
|
92
|
+
it "provides access to scope" do
|
93
|
+
|
94
|
+
with_template("whatever.json.rep", <<-RUBY)
|
95
|
+
r.element :author, @mike do
|
96
|
+
r.element :name
|
97
|
+
end
|
98
|
+
RUBY
|
99
|
+
|
100
|
+
scope = Object.new
|
101
|
+
scope.instance_eval do
|
102
|
+
@mike = OpenStruct.new(:name => "Mike")
|
103
|
+
end
|
104
|
+
render(scope)
|
105
|
+
|
106
|
+
resulting_json.should == undent(<<-JSON)
|
107
|
+
{
|
108
|
+
"name": "Mike"
|
109
|
+
}
|
110
|
+
JSON
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
it "provides access to local variables" do
|
115
|
+
|
116
|
+
with_template("whatever.json.rep", <<-RUBY)
|
117
|
+
r.element :author, author do
|
118
|
+
r.element :name
|
119
|
+
end
|
120
|
+
RUBY
|
121
|
+
|
122
|
+
render(Object.new, {:author => OpenStruct.new(:name => "Mike")})
|
123
|
+
|
124
|
+
resulting_json.should == undent(<<-JSON)
|
125
|
+
{
|
126
|
+
"name": "Mike"
|
127
|
+
}
|
128
|
+
JSON
|
129
|
+
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
@@ -0,0 +1,270 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require "rexml/document"
|
4
|
+
|
5
|
+
shared_examples_for "an XML Representative" do
|
6
|
+
|
7
|
+
describe "for some 'subject'" do
|
8
|
+
|
9
|
+
before do
|
10
|
+
@subject = OpenStruct.new(:name => "Fred", :width => 200, :vehicle => OpenStruct.new(:year => "1959", :make => "Chevrolet"))
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "#element" do
|
14
|
+
|
15
|
+
it "generates an element with content extracted from the subject" do
|
16
|
+
r.element :name
|
17
|
+
resulting_xml.should == %(<name>Fred</name>)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "dasherizes the property name" do
|
21
|
+
@subject.full_name = "Fredrick"
|
22
|
+
r.element :full_name
|
23
|
+
resulting_xml.should == %(<full-name>Fredrick</full-name>)
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "with attributes" do
|
27
|
+
|
28
|
+
it "generates attributes on the element" do
|
29
|
+
r.element :name, :lang => "fr"
|
30
|
+
resulting_xml.should == %(<name lang="fr">Fred</name>)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "dasherizes the attribute name" do
|
34
|
+
r.element :name, :sourced_from => "phonebook"
|
35
|
+
resulting_xml.should == %(<name sourced-from="phonebook">Fred</name>)
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "whose value supports #to_proc" do
|
39
|
+
|
40
|
+
it "calls the Proc on the subject to generate a value" do
|
41
|
+
r.element :name, :rev => :reverse
|
42
|
+
resulting_xml.should == %(<name rev="derF">Fred</name>)
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "with value nil" do
|
48
|
+
|
49
|
+
it "omits the attribute" do
|
50
|
+
r.element :name, :lang => nil
|
51
|
+
resulting_xml.should == %(<name>Fred</name>)
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "with an explicit value" do
|
59
|
+
|
60
|
+
it "generates an element with explicitly provided content" do
|
61
|
+
r.element :name, "Bloggs"
|
62
|
+
resulting_xml.should == %(<name>Bloggs</name>)
|
63
|
+
end
|
64
|
+
|
65
|
+
describe "AND attributes" do
|
66
|
+
|
67
|
+
it "generates attributes on the element" do
|
68
|
+
r.element :name, "Bloggs", :lang => "fr"
|
69
|
+
resulting_xml.should == %(<name lang="fr">Bloggs</name>)
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
describe "with a value argument that supports #to_proc" do
|
77
|
+
|
78
|
+
it "calls the Proc on the subject to generate a value" do
|
79
|
+
r.element :name, :width
|
80
|
+
resulting_xml.should == %(<name>200</name>)
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
describe "with value argument :self" do
|
86
|
+
|
87
|
+
it "doesn't alter the subject" do
|
88
|
+
r.element :info, :self do
|
89
|
+
r.element :name
|
90
|
+
end
|
91
|
+
resulting_xml.should == %(<info><name>Fred</name></info>)
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
describe "with value argument nil" do
|
97
|
+
|
98
|
+
it "builds an empty element" do
|
99
|
+
r.element :name, nil
|
100
|
+
resulting_xml.should == %(<name/>)
|
101
|
+
end
|
102
|
+
|
103
|
+
describe "and attributes" do
|
104
|
+
|
105
|
+
it "omits attributes derived from the subject" do
|
106
|
+
r.element :name, nil, :size => :size
|
107
|
+
resulting_xml.should == %(<name/>)
|
108
|
+
end
|
109
|
+
|
110
|
+
it "retains attributes with explicit values" do
|
111
|
+
r.element :name, nil, :lang => "en"
|
112
|
+
resulting_xml.should == %(<name lang="en"/>)
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
describe "and a block" do
|
118
|
+
|
119
|
+
it "doesn't call the block" do
|
120
|
+
r.element :name, nil do
|
121
|
+
raise "hell"
|
122
|
+
end
|
123
|
+
resulting_xml.should == %(<name/>)
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
|
130
|
+
describe "with a block" do
|
131
|
+
|
132
|
+
it "generates nested elements" do
|
133
|
+
r.element :vehicle do
|
134
|
+
r.element :year
|
135
|
+
r.element :make
|
136
|
+
end
|
137
|
+
resulting_xml.should == %(<vehicle><year>1959</year><make>Chevrolet</make></vehicle>)
|
138
|
+
end
|
139
|
+
|
140
|
+
it "yields each new subject" do
|
141
|
+
r.element :vehicle do |vehicle|
|
142
|
+
r.element :year, vehicle.year
|
143
|
+
end
|
144
|
+
resulting_xml.should == %(<vehicle><year>1959</year></vehicle>)
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
148
|
+
|
149
|
+
describe "with an EMPTY block" do
|
150
|
+
|
151
|
+
it "generates an empty element" do
|
152
|
+
r.element :vehicle, :year => :year, &r.empty
|
153
|
+
resulting_xml.should == %(<vehicle year="1959"/>)
|
154
|
+
end
|
155
|
+
|
156
|
+
end
|
157
|
+
|
158
|
+
end
|
159
|
+
|
160
|
+
describe "#list_of" do
|
161
|
+
|
162
|
+
before do
|
163
|
+
@subject.nick_names = ["Freddie", "Knucklenose"]
|
164
|
+
end
|
165
|
+
|
166
|
+
it "generates an array element" do
|
167
|
+
r.list_of(:nick_names)
|
168
|
+
resulting_xml.should == %(<nick-names type="array"><nick-name>Freddie</nick-name><nick-name>Knucklenose</nick-name></nick-names>)
|
169
|
+
end
|
170
|
+
|
171
|
+
describe "with :list_attributes" do
|
172
|
+
|
173
|
+
it "attaches attributes to the array element" do
|
174
|
+
r.list_of(:nick_names, :list_attributes => {:color => "blue", :size => :size})
|
175
|
+
array_element_attributes = REXML::Document.new(resulting_xml).root.attributes
|
176
|
+
array_element_attributes["type"].should == "array"
|
177
|
+
array_element_attributes["color"].should == "blue"
|
178
|
+
array_element_attributes["size"].should == "2"
|
179
|
+
array_element_attributes.size.should == 3
|
180
|
+
end
|
181
|
+
|
182
|
+
end
|
183
|
+
|
184
|
+
describe "with :item_attributes" do
|
185
|
+
|
186
|
+
it "attaches attributes to each item element" do
|
187
|
+
r.list_of(:nick_names, :item_attributes => {:length => :size})
|
188
|
+
resulting_xml.should == %(<nick-names type="array"><nick-name length="7">Freddie</nick-name><nick-name length="11">Knucklenose</nick-name></nick-names>)
|
189
|
+
end
|
190
|
+
|
191
|
+
end
|
192
|
+
|
193
|
+
describe "with an explicit :item_name" do
|
194
|
+
it "uses the name provided" do
|
195
|
+
r.list_of(:nick_names, :item_name => :nick)
|
196
|
+
resulting_xml.should == %(<nick-names type="array"><nick>Freddie</nick><nick>Knucklenose</nick></nick-names>)
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
describe "with an argument that resolves to nil" do
|
201
|
+
|
202
|
+
it "omits the attribute" do
|
203
|
+
r.list_of(:services) do
|
204
|
+
r.date
|
205
|
+
end
|
206
|
+
resulting_xml.should == %(<services/>)
|
207
|
+
end
|
208
|
+
|
209
|
+
end
|
210
|
+
|
211
|
+
describe "with a block" do
|
212
|
+
|
213
|
+
it "generates a nested element for each list element" do
|
214
|
+
r.list_of(:nick_names) do
|
215
|
+
r.element :length
|
216
|
+
end
|
217
|
+
resulting_xml.should == %(<nick-names type="array"><nick-name><length>7</length></nick-name><nick-name><length>11</length></nick-name></nick-names>)
|
218
|
+
end
|
219
|
+
|
220
|
+
end
|
221
|
+
|
222
|
+
describe "with an EMPTY block" do
|
223
|
+
|
224
|
+
it "generates empty elements for each list element" do
|
225
|
+
r.list_of(:nick_names, :item_attributes => {:value => :to_s}, &r.empty)
|
226
|
+
resulting_xml.should == %(<nick-names type="array"><nick-name value="Freddie"/><nick-name value="Knucklenose"/></nick-names>)
|
227
|
+
end
|
228
|
+
|
229
|
+
end
|
230
|
+
|
231
|
+
describe "with :item_attributes AND block" do
|
232
|
+
|
233
|
+
it "generates attributes and nested elements" do
|
234
|
+
r.list_of(:nick_names, :item_attributes => {:length => :size}) do
|
235
|
+
r.element :reverse
|
236
|
+
end
|
237
|
+
resulting_xml.should == %(<nick-names type="array"><nick-name length="7"><reverse>eidderF</reverse></nick-name><nick-name length="11"><reverse>esonelkcunK</reverse></nick-name></nick-names>)
|
238
|
+
end
|
239
|
+
|
240
|
+
end
|
241
|
+
|
242
|
+
end
|
243
|
+
|
244
|
+
describe "#representing" do
|
245
|
+
|
246
|
+
it "selects a new subject without generating an element" do
|
247
|
+
r.representing :vehicle do
|
248
|
+
r.element :make
|
249
|
+
end
|
250
|
+
resulting_xml.should == %(<make>Chevrolet</make>)
|
251
|
+
end
|
252
|
+
|
253
|
+
end
|
254
|
+
|
255
|
+
describe "#comment" do
|
256
|
+
|
257
|
+
it "inserts a comment" do
|
258
|
+
r.element :vehicle do
|
259
|
+
r.comment "Year of manufacture"
|
260
|
+
r.element :year
|
261
|
+
end
|
262
|
+
resulting_xml.should ==
|
263
|
+
%(<vehicle><!-- Year of manufacture --><year>1959</year></vehicle>)
|
264
|
+
end
|
265
|
+
|
266
|
+
end
|
267
|
+
|
268
|
+
end
|
269
|
+
|
270
|
+
end
|