bldr 0.6.0 → 0.7.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/.travis.yml +1 -2
- data/Gemfile +1 -0
- data/HISTORY.md +11 -1
- data/MIT-LICENSE +1 -1
- data/README.md +72 -2
- data/bldr.gemspec +3 -3
- data/lib/bldr/node.rb +43 -11
- data/lib/bldr/template.rb +3 -0
- data/lib/bldr/version.rb +1 -1
- data/lib/sinatra/bldr.rb +5 -3
- data/spec/fixtures/ivar.bldr +3 -0
- data/spec/fixtures/nested_ivars.bldr +5 -0
- data/spec/fixtures/nested_objects.json.bldr +2 -2
- data/spec/functional/tilt_template_spec.rb +191 -93
- data/spec/integration/sinatra_spec.rb +21 -1
- data/spec/models/song.rb +6 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/unit/node_spec.rb +501 -490
- metadata +20 -14
@@ -55,6 +55,26 @@ describe "Using Bldr with a sinatra app" do
|
|
55
55
|
get '/root_partial' do
|
56
56
|
bldr :'fixtures/root_partial'
|
57
57
|
end
|
58
|
+
|
59
|
+
get '/ivar' do
|
60
|
+
@person = Person.new('bert', 99)
|
61
|
+
bldr :'fixtures/ivar'
|
62
|
+
end
|
63
|
+
|
64
|
+
get '/nested_ivars' do
|
65
|
+
@person = Person.new('bert', 99)
|
66
|
+
bldr :'fixtures/nested_ivars'
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'passes ivars through to the template' do
|
71
|
+
response = Rack::MockRequest.new(TestApp).get('/ivar')
|
72
|
+
decode(response.body).should == {'person' => {'name' => 'bert', 'age' => 99}}
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'makes ivars available in nested objects' do
|
76
|
+
response = Rack::MockRequest.new(TestApp).get('/nested_ivars')
|
77
|
+
decode(response.body).should == {'person' => {'name' => 'bert', 'age' => 99}}
|
58
78
|
end
|
59
79
|
|
60
80
|
it "properly renders a template that only contains a template call" do
|
@@ -118,4 +138,4 @@ describe "access to the locals hash inside sinatra bldr templates" do
|
|
118
138
|
response = Rack::MockRequest.new(Locals).get('/')
|
119
139
|
MultiJson.decode(response.body)['locals']['key'].should == 'val'
|
120
140
|
end
|
121
|
-
end
|
141
|
+
end
|
data/spec/models/song.rb
ADDED
data/spec/spec_helper.rb
CHANGED
data/spec/unit/node_spec.rb
CHANGED
@@ -1,176 +1,157 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
ERROR_MESSAGES = { :attribute_lambda_one_argument => "You may only pass one argument to #attribute when using the block syntax.",
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
it "returns stuff" do
|
16
|
-
node.attribute(:age).should == node
|
17
|
-
end
|
18
|
-
end
|
4
|
+
:attribute_inferred_missing_one_argument => "#attribute can't be used when there is no current_object.",
|
5
|
+
:attribute_more_than_two_arg => "You cannot pass more than two arguments to #attribute.",
|
6
|
+
:attribute_inferred_missing_arity_too_large => "You cannot use a block of arity > 0 if current_object is not present.",
|
7
|
+
:attributes_inferred_missing => "No current_object to apply #attributes to." }
|
8
|
+
|
9
|
+
module Bldr
|
10
|
+
describe Node, "#attributes" do
|
11
|
+
let(:person) {
|
12
|
+
Person.new('john', 25)
|
13
|
+
}
|
14
|
+
let(:node) { Bldr::Node.new(person) }
|
19
15
|
|
20
|
-
|
21
|
-
|
22
|
-
it "renders the object exactly as it appears when passed an object with no block" do
|
23
|
-
obj = {'key' => 'val', 'nested' => {'key' => 'val'}}
|
24
|
-
node = node_wrap do
|
25
|
-
object obj
|
26
|
-
end
|
27
|
-
node.result.should == obj
|
16
|
+
it "returns stuff" do
|
17
|
+
node.attribute(:age).should == node
|
28
18
|
end
|
29
19
|
end
|
30
20
|
|
31
|
-
|
21
|
+
describe Node, "#attribute" do
|
22
|
+
it "raises an exception when passed more than one argument and a block" do
|
23
|
+
expect {
|
24
|
+
Node.new {
|
25
|
+
attribute(:one, :two) do |person|
|
26
|
+
"..."
|
27
|
+
end
|
28
|
+
}
|
29
|
+
}.to raise_error(ArgumentError, ERROR_MESSAGES[:attribute_lambda_one_argument])
|
30
|
+
end
|
32
31
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
32
|
+
it "raises an exception when passed more than two args" do
|
33
|
+
expect {
|
34
|
+
Node.new {
|
35
|
+
attribute(:one, :two, :three)
|
36
|
+
}
|
37
|
+
}.to raise_error(ArgumentError, ERROR_MESSAGES[:attribute_more_than_two_arg])
|
37
38
|
end
|
38
39
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
40
|
+
it "errors on 1 argument since there is no inferred object" do
|
41
|
+
expect {
|
42
|
+
Node.new {
|
43
|
+
attribute(:one)
|
44
|
+
}
|
45
|
+
}.to raise_error(ArgumentError, ERROR_MESSAGES[:attribute_inferred_missing_one_argument])
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "wrapped in an object block" do
|
49
|
+
it "renders 2 arguments statically" do
|
50
|
+
node = Node.new do
|
51
|
+
object :person do
|
52
|
+
attribute(:name, "alex")
|
53
|
+
end
|
54
|
+
end
|
55
|
+
node.result.should == {:person => {:name => 'alex'}}
|
48
56
|
end
|
49
57
|
|
50
|
-
it "
|
51
|
-
|
52
|
-
|
53
|
-
attribute(:
|
54
|
-
|
55
|
-
|
58
|
+
it "renders 1 argument and one lambda with zero arity" do
|
59
|
+
node = Node.new do
|
60
|
+
object :person do
|
61
|
+
attribute(:name) { "alex" }
|
62
|
+
end
|
63
|
+
end
|
64
|
+
node.result.should == {:person => {:name => 'alex'}}
|
56
65
|
end
|
57
66
|
|
58
|
-
it "
|
59
|
-
|
60
|
-
|
61
|
-
attribute(:
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
}.to raise_error(ArgumentError, ERROR_MESSAGES[:attribute_lambda_one_argument])
|
67
|
+
it "renders 1 argument to the inferred object" do
|
68
|
+
node = Node.new do
|
69
|
+
object :person => Person.new('alex', 25) do
|
70
|
+
attribute(:name)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
node.result.should == {:person => {:name => 'alex'}}
|
66
74
|
end
|
67
75
|
|
68
|
-
it "
|
69
|
-
|
70
|
-
|
71
|
-
attribute(:
|
72
|
-
|
73
|
-
|
76
|
+
it "renders 1 argument hash to the inferred object as the different key" do
|
77
|
+
node = Node.new do
|
78
|
+
object :person => Person.new('alex', 25) do
|
79
|
+
attribute(:fake => :name)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
node.result.should == {:person => {:fake => 'alex'}}
|
74
83
|
end
|
75
84
|
|
76
85
|
it "renders 2 arguments statically" do
|
77
|
-
node =
|
78
|
-
|
86
|
+
node = Node.new do
|
87
|
+
object :person => Person.new('alex', 25) do
|
88
|
+
attribute(:name, 'ian')
|
89
|
+
end
|
90
|
+
end
|
91
|
+
node.result.should == {:person => {:name => 'ian'}}
|
79
92
|
end
|
80
93
|
|
81
94
|
it "renders 1 argument and one lambda with zero arity" do
|
82
|
-
node =
|
83
|
-
|
84
|
-
|
95
|
+
node = Node.new do
|
96
|
+
object :person => Person.new('alex', 25) do
|
97
|
+
attribute(:name) { 'ian' }
|
85
98
|
end
|
86
|
-
|
87
|
-
node.result.should == {:name => 'alex'}
|
88
|
-
end
|
99
|
+
end
|
89
100
|
|
90
|
-
|
91
|
-
expect {
|
92
|
-
node_wrap {
|
93
|
-
attribute(:name) do |name|
|
94
|
-
name
|
95
|
-
end
|
96
|
-
}
|
97
|
-
}.to raise_error(ArgumentError, ERROR_MESSAGES[:attribute_inferred_missing_arity_too_large])
|
101
|
+
node.result.should == {:person => {:name => 'ian'}}
|
98
102
|
end
|
99
103
|
|
100
|
-
it "
|
101
|
-
node =
|
102
|
-
|
103
|
-
|
104
|
-
|
104
|
+
it "renders 1 argument and one lambda with arity 1" do
|
105
|
+
node = Node.new do
|
106
|
+
object :person => Person.new('alex', 25) do
|
107
|
+
attribute(:name) { |person| person.name }
|
108
|
+
end
|
109
|
+
end
|
105
110
|
|
106
|
-
|
107
|
-
it "errors since current_object is nil" do
|
108
|
-
expect {
|
109
|
-
node_wrap {
|
110
|
-
attributes(:name)
|
111
|
-
}
|
112
|
-
}.to raise_error(ArgumentError, ERROR_MESSAGES[:attributes_inferred_missing])
|
111
|
+
node.result.should == {:person => {:name => 'alex'}}
|
113
112
|
end
|
114
|
-
end
|
115
|
-
end
|
116
113
|
|
117
|
-
|
114
|
+
it "renders nil attributes" do
|
115
|
+
node = Node.new do
|
116
|
+
object :person => Person.new('alex') do
|
117
|
+
attribute :age
|
118
|
+
end
|
119
|
+
end
|
118
120
|
|
119
|
-
|
120
|
-
Bldr::Node.new do
|
121
|
-
object(:person, &block)
|
121
|
+
node.result.should == {:person => {:age => nil}}
|
122
122
|
end
|
123
123
|
end
|
124
124
|
|
125
|
-
describe
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
node_wrap {
|
130
|
-
attribute(:one, :two) do |person|
|
131
|
-
"..."
|
132
|
-
end
|
133
|
-
}
|
134
|
-
}.to raise_error(ArgumentError, ERROR_MESSAGES[:attribute_lambda_one_argument])
|
135
|
-
end
|
136
|
-
it "errors on 3 arguments" do
|
137
|
-
expect {
|
138
|
-
node_wrap {
|
139
|
-
attribute(:one, :two, :three)
|
140
|
-
}
|
141
|
-
}.to raise_error(ArgumentError, ERROR_MESSAGES[:attribute_more_than_two_arg])
|
142
|
-
end
|
143
|
-
it "errors on 2 arguments and a lambda" do
|
144
|
-
expect {
|
145
|
-
node_wrap {
|
146
|
-
attribute(:one, :two) do |person|
|
147
|
-
"..."
|
148
|
-
end
|
149
|
-
}
|
150
|
-
}.to raise_error(ArgumentError, ERROR_MESSAGES[:attribute_lambda_one_argument])
|
125
|
+
describe 'when in static key-value form (with two arguments)' do
|
126
|
+
it "renders 2 arguments statically as key, value" do
|
127
|
+
node = Node.new { attribute(:name, "alex") }
|
128
|
+
node.result.should == {:name => 'alex'}
|
151
129
|
end
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
}
|
157
|
-
}.to raise_error(ArgumentError, ERROR_MESSAGES[:attribute_inferred_missing_one_argument])
|
130
|
+
|
131
|
+
it "renders null attributes to null, not 'null'" do
|
132
|
+
node = Node.new { attribute(:name, nil) }
|
133
|
+
node.result.should == {:name => nil}
|
158
134
|
end
|
159
|
-
|
160
|
-
|
161
|
-
|
135
|
+
end
|
136
|
+
|
137
|
+
describe 'when in dynamic block form (with 1 argument and a block)' do
|
138
|
+
it 'sets the attribute default context to bldr node' do
|
139
|
+
node = Node.new { attribute(:key) { self.class } }
|
140
|
+
node.result[:key].should == ::Bldr::Node
|
162
141
|
end
|
163
|
-
|
164
|
-
|
142
|
+
|
143
|
+
it "uses the argument as the key and the block result as the value" do
|
144
|
+
node = Node.new {
|
165
145
|
attribute(:name) do
|
166
146
|
"alex"
|
167
147
|
end
|
168
148
|
}
|
169
|
-
node.result.should == {:
|
149
|
+
node.result.should == {:name => 'alex'}
|
170
150
|
end
|
151
|
+
|
171
152
|
it "errors on 1 argument and one lambda with arity 1" do
|
172
153
|
expect {
|
173
|
-
|
154
|
+
Node.new {
|
174
155
|
attribute(:name) do |name|
|
175
156
|
name
|
176
157
|
end
|
@@ -179,520 +160,550 @@ describe "Node#object" do
|
|
179
160
|
end
|
180
161
|
end
|
181
162
|
|
182
|
-
|
163
|
+
end
|
183
164
|
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
165
|
+
describe Node, "#object" do
|
166
|
+
it 'is passes block the block variable to the block' do
|
167
|
+
denver = Person.new('John Denver')
|
168
|
+
node = Node.new do
|
169
|
+
object :person => denver do |jd|
|
170
|
+
attribute(:name) { jd.name }
|
171
|
+
end
|
190
172
|
end
|
191
173
|
|
174
|
+
node.result.should == {:person => {:name => 'John Denver'}}
|
192
175
|
end
|
193
176
|
|
194
|
-
|
177
|
+
context "rendering an object exactly as it exists" do
|
178
|
+
it "renders the object exactly as it appears when passed an object with no block" do
|
179
|
+
obj = {'key' => 'val', 'nested' => {'key' => 'val'}}
|
180
|
+
node = node_wrap do
|
181
|
+
object obj
|
182
|
+
end
|
183
|
+
node.result.should == obj
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
context "a zero arg root object node" do
|
195
188
|
|
196
|
-
|
189
|
+
def wrap(&block)
|
190
|
+
Bldr::Node.new do
|
191
|
+
object(&block)
|
192
|
+
end
|
193
|
+
end
|
197
194
|
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
195
|
+
describe "#attributes" do
|
196
|
+
it "errors since current_object is nil" do
|
197
|
+
expect {
|
198
|
+
node_wrap {
|
199
|
+
attributes(:name)
|
200
|
+
}
|
201
|
+
}.to raise_error(ArgumentError, ERROR_MESSAGES[:attributes_inferred_missing])
|
202
|
+
end
|
202
203
|
end
|
203
204
|
end
|
204
205
|
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
206
|
+
context "a single arg root object node" do
|
207
|
+
|
208
|
+
def wrap(&block)
|
209
|
+
Bldr::Node.new do
|
210
|
+
object(:person, &block)
|
211
|
+
end
|
210
212
|
end
|
211
213
|
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
214
|
+
describe "#attributes" do
|
215
|
+
|
216
|
+
it "errors since current_object is nil" do
|
217
|
+
expect {
|
218
|
+
node_wrap {
|
219
|
+
attributes(:name)
|
220
|
+
}
|
221
|
+
}.to raise_error(ArgumentError, ERROR_MESSAGES[:attributes_inferred_missing])
|
222
|
+
end
|
218
223
|
end
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
+
end
|
225
|
+
|
226
|
+
context "a hash-arg root object node" do
|
227
|
+
def wrap(&block)
|
228
|
+
alex = Person.new('alex').tap { |p| p.age = 25; p }
|
229
|
+
Bldr::Node.new do
|
230
|
+
object(:person => alex, &block)
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
|
235
|
+
describe "#attributes" do
|
236
|
+
describe "when an object key is passed a null value" do
|
237
|
+
subject {
|
238
|
+
node = node_wrap do
|
239
|
+
object(:person => nil) do
|
240
|
+
attributes(:one, :two) do |person|
|
241
|
+
"..."
|
242
|
+
end
|
243
|
+
end
|
224
244
|
end
|
225
245
|
}
|
226
|
-
}.to raise_error(ArgumentError, ERROR_MESSAGES[:attribute_lambda_one_argument])
|
227
|
-
end
|
228
|
-
it "renders 1 argument to the inferred object" do
|
229
|
-
node = wrap { attribute(:name) }
|
230
|
-
node.result.should == {:person => {:name => 'alex'}}
|
231
|
-
end
|
232
|
-
it "renders 1 argument hash to the inferred object as the different key" do
|
233
|
-
node = wrap { attribute(:fake => :name) }
|
234
|
-
node.result.should == {:person => {:fake => 'alex'}}
|
235
|
-
end
|
236
|
-
it "renders 2 arguments statically" do
|
237
|
-
node = wrap { attribute(:name, "ian") }
|
238
|
-
node.result.should == {:person => {:name => 'ian'}}
|
239
|
-
end
|
240
|
-
it "renders 1 argument and one lambda with zero arity" do
|
241
|
-
node = wrap { attribute(:name){"ian"} }
|
242
|
-
node.result.should == {:person => {:name => 'ian'}}
|
243
|
-
end
|
244
|
-
it "renders 1 argument and one lambda with arity 1" do
|
245
|
-
node = wrap { attribute(:name){|person| person.name} }
|
246
|
-
node.result.should == {:person => {:name => 'alex'}}
|
247
|
-
end
|
248
|
-
it "renders nil attributes" do
|
249
|
-
node = node_wrap do
|
250
|
-
object :person => Person.new('alex') do
|
251
|
-
attribute :age
|
252
|
-
end
|
253
|
-
end
|
254
246
|
|
255
|
-
|
256
|
-
|
247
|
+
it "does not raise an inferred object error" do
|
248
|
+
expect {
|
249
|
+
subject
|
250
|
+
}.not_to raise_error(ArgumentError, ERROR_MESSAGES[:attributes_inferred_missing])
|
251
|
+
end
|
257
252
|
|
258
|
-
|
253
|
+
its(:result) { should == {} }
|
254
|
+
end
|
259
255
|
|
260
|
-
|
261
|
-
|
262
|
-
|
256
|
+
it "renders each argument against the inferred object" do
|
257
|
+
node = wrap { attributes(:name, :age) }
|
258
|
+
node.result.should == {:person => {:name => 'alex', :age => 25}}
|
259
|
+
end
|
260
|
+
it "renders nil attributes" do
|
263
261
|
node = node_wrap do
|
264
|
-
object
|
265
|
-
attributes
|
266
|
-
"..."
|
267
|
-
end
|
262
|
+
object :person => Person.new('alex') do
|
263
|
+
attributes :name, :age
|
268
264
|
end
|
269
265
|
end
|
270
|
-
}
|
271
266
|
|
272
|
-
|
273
|
-
expect {
|
274
|
-
subject
|
275
|
-
}.not_to raise_error(ArgumentError, ERROR_MESSAGES[:attributes_inferred_missing])
|
267
|
+
node.result.should == {:person => {:name => 'alex', :age => nil}}
|
276
268
|
end
|
277
269
|
|
278
|
-
its(:result) { should == {} }
|
279
270
|
end
|
280
271
|
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
it "renders nil attributes" do
|
272
|
+
end
|
273
|
+
|
274
|
+
describe "embedded objects" do
|
275
|
+
it "evaluates the block and returns json" do
|
286
276
|
node = node_wrap do
|
287
|
-
object
|
288
|
-
attributes :name
|
277
|
+
object(:dude => Person.new("alex")) do
|
278
|
+
attributes :name
|
279
|
+
|
280
|
+
object(:bro => Person.new("john")) do
|
281
|
+
attributes :name
|
282
|
+
end
|
289
283
|
end
|
290
284
|
end
|
291
285
|
|
292
|
-
node.result.should == {:
|
286
|
+
node.result.should == {:dude => {:name => 'alex', :bro => {:name => 'john'}}}
|
293
287
|
end
|
294
|
-
|
295
288
|
end
|
296
289
|
|
297
290
|
end
|
298
291
|
|
299
|
-
describe "
|
300
|
-
it "
|
292
|
+
describe "Node#result" do
|
293
|
+
it "returns an empty hash when not passed an object" do
|
294
|
+
Bldr::Node.new.result.should == {}
|
295
|
+
end
|
296
|
+
|
297
|
+
it "a document with a single node with no nesting" do
|
301
298
|
node = node_wrap do
|
302
|
-
object
|
299
|
+
object :person => Person.new('alex') do
|
303
300
|
attributes :name
|
304
|
-
|
305
|
-
object(:bro => Person.new("john")) do
|
306
|
-
attributes :name
|
307
|
-
end
|
308
301
|
end
|
309
302
|
end
|
310
303
|
|
311
|
-
node.result.should == {:
|
304
|
+
node.result.should == {:person => {:name => 'alex'}}
|
312
305
|
end
|
313
|
-
end
|
314
306
|
|
315
|
-
|
307
|
+
it "works for multiple top-level objects" do
|
308
|
+
alex, john = Person.new("alex"), Person.new("john")
|
316
309
|
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
310
|
+
node = node_wrap do
|
311
|
+
object(:alex => alex) do
|
312
|
+
attributes :name
|
313
|
+
end
|
321
314
|
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
attributes :name
|
315
|
+
object(:john => john) do
|
316
|
+
attributes :name
|
317
|
+
end
|
326
318
|
end
|
327
|
-
end
|
328
319
|
|
329
|
-
|
330
|
-
|
320
|
+
node.result.should == {:alex => {:name => 'alex'}, :john => {:name => 'john'}}
|
321
|
+
end
|
331
322
|
|
332
|
-
|
333
|
-
|
323
|
+
it "recursively renders nested objects" do
|
324
|
+
node = node_wrap do
|
325
|
+
object :alex => Person.new("alex") do
|
326
|
+
attributes :name
|
334
327
|
|
335
|
-
|
336
|
-
|
337
|
-
|
328
|
+
object :friend => Person.new("john") do
|
329
|
+
attributes :name
|
330
|
+
end
|
331
|
+
end
|
338
332
|
end
|
339
333
|
|
340
|
-
|
341
|
-
|
342
|
-
|
334
|
+
node.result.should == {
|
335
|
+
:alex => {
|
336
|
+
:name => 'alex', :friend => {:name => 'john'}
|
337
|
+
}
|
338
|
+
}
|
343
339
|
end
|
344
340
|
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
attributes :name
|
341
|
+
describe "#attributes syntax" do
|
342
|
+
it "allows a hash to be sent where the keys are the result keys" do
|
343
|
+
alex = Person.new("alex").tap do |p|
|
344
|
+
p.age = 25
|
345
|
+
p
|
346
|
+
end
|
352
347
|
|
353
|
-
|
354
|
-
|
348
|
+
node = node_wrap do
|
349
|
+
object(:person => alex) do
|
350
|
+
attributes({:surname => :name}, :age)
|
351
|
+
end
|
355
352
|
end
|
353
|
+
|
354
|
+
node.result.should == {:person => {:surname => 'alex', :age => 25}}
|
356
355
|
end
|
357
356
|
end
|
358
|
-
|
359
|
-
node.result.should == {
|
360
|
-
:alex => {
|
361
|
-
:name => 'alex',
|
362
|
-
:friend => {:name => 'john'}
|
363
|
-
}
|
364
|
-
}
|
365
357
|
end
|
366
358
|
|
367
|
-
describe "#
|
368
|
-
it "
|
369
|
-
alex = Person.new("alex").tap do |p|
|
370
|
-
p.age = 25
|
371
|
-
p
|
372
|
-
end
|
373
|
-
|
359
|
+
describe Node, "#to_json" do
|
360
|
+
it "recursively returns the result json" do
|
374
361
|
node = node_wrap do
|
375
|
-
object
|
376
|
-
attributes
|
362
|
+
object :person => Person.new("alex") do
|
363
|
+
attributes :name
|
364
|
+
|
365
|
+
object :friend => Person.new("pete", 30) do
|
366
|
+
attributes :name, :age
|
367
|
+
end
|
377
368
|
end
|
378
369
|
end
|
379
370
|
|
380
|
-
node.result.should == {
|
371
|
+
node.result.should == {
|
372
|
+
:person => {
|
373
|
+
:name => 'alex',
|
374
|
+
:friend => {:name => 'pete', :age => 30}
|
375
|
+
}
|
376
|
+
}
|
381
377
|
end
|
382
|
-
end
|
383
|
-
end
|
384
378
|
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
object :person => Person.new("alex") do
|
389
|
-
attributes :name
|
390
|
-
|
391
|
-
object :friend => Person.new("pete", 30) do
|
379
|
+
it "returns null values for nil attributes" do
|
380
|
+
node = node_wrap do
|
381
|
+
object :person => Person.new('alex') do
|
392
382
|
attributes :name, :age
|
393
383
|
end
|
394
384
|
end
|
395
|
-
end
|
396
385
|
|
397
|
-
|
398
|
-
:person
|
399
|
-
|
400
|
-
:friend => {:name => 'pete', :age => 30}
|
401
|
-
}
|
402
|
-
}
|
386
|
+
node.result[:person].should have_key(:age)
|
387
|
+
node.result[:person][:age].should be_nil
|
388
|
+
end
|
403
389
|
end
|
404
390
|
|
405
|
-
|
406
|
-
|
407
|
-
object
|
408
|
-
|
391
|
+
describe Node, "#collection" do
|
392
|
+
context "when passed an object with no block" do
|
393
|
+
it "renders the object exactly as it exists" do
|
394
|
+
coll = [{'key' => 'val'}]
|
395
|
+
node = node_wrap do
|
396
|
+
collection coll
|
397
|
+
end
|
398
|
+
|
399
|
+
node.result.should == coll
|
409
400
|
end
|
410
|
-
end
|
411
401
|
|
412
|
-
|
413
|
-
|
414
|
-
end
|
415
|
-
end
|
402
|
+
it "renders complex collection objects correctly" do
|
403
|
+
hobbies = [{'name' => "Gym"}, {'name' => "Tan"}, {'name' => "Laundry"}]
|
416
404
|
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
end
|
405
|
+
node = node_wrap do
|
406
|
+
object 'person' => Person.new("Alex") do
|
407
|
+
attribute :name
|
408
|
+
collection 'hobbies' => hobbies
|
409
|
+
end
|
410
|
+
end
|
424
411
|
|
425
|
-
|
412
|
+
node.result.should == {'person' => {:name => "Alex", 'hobbies' => hobbies}}
|
413
|
+
end
|
426
414
|
end
|
427
415
|
|
428
|
-
it "
|
429
|
-
|
416
|
+
it "iterates through the collection and passes each item as a block variable" do
|
417
|
+
denver = Person.new('John Denver')
|
418
|
+
songs = [Song.new('Rocky Mountain High'), Song.new('Take Me Home, Country Roads')]
|
430
419
|
|
431
|
-
node =
|
432
|
-
object
|
420
|
+
node = Node.new do
|
421
|
+
object :artist => denver do
|
433
422
|
attribute :name
|
434
|
-
|
423
|
+
|
424
|
+
collection :songs => songs do |song|
|
425
|
+
attribute(:name) { song.name }
|
426
|
+
end
|
435
427
|
end
|
436
428
|
end
|
437
429
|
|
438
|
-
node.result.should == {
|
430
|
+
node.result.should == {
|
431
|
+
:artist => {:name => 'John Denver',
|
432
|
+
:songs => [{:name => 'Rocky Mountain High'},
|
433
|
+
{:name => 'Take Me Home, Country Roads'}
|
434
|
+
]
|
435
|
+
}
|
436
|
+
}
|
439
437
|
end
|
440
|
-
end
|
441
|
-
|
442
|
-
it "iterates through the collection and renders them as nodes" do
|
443
|
-
node = node_wrap do
|
444
|
-
object :person => Person.new('alex', 26) do
|
445
|
-
attributes :name, :age
|
446
438
|
|
447
|
-
|
439
|
+
it "iterates through the collection and renders them as nodes" do
|
440
|
+
node = node_wrap do
|
441
|
+
object :person => Person.new('alex', 26) do
|
448
442
|
attributes :name, :age
|
443
|
+
|
444
|
+
collection :friends => [Person.new('john', 24), Person.new('jeff', 25)] do
|
445
|
+
attributes :name, :age
|
446
|
+
end
|
449
447
|
end
|
450
448
|
end
|
451
|
-
end
|
452
449
|
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
450
|
+
node.result.should == {
|
451
|
+
:person => {
|
452
|
+
:name => 'alex', :age => 26,
|
453
|
+
:friends => [
|
454
|
+
{:name => 'john', :age => 24},
|
455
|
+
{:name => 'jeff', :age => 25}]
|
456
|
+
}
|
457
457
|
}
|
458
|
-
}
|
459
|
-
end
|
460
|
-
|
461
|
-
# @todo fix this
|
462
|
-
it "renders properly when a collection is the named root node" do
|
463
|
-
nodes = node_wrap do
|
464
|
-
collection :people => [Person.new('bert'), Person.new('ernie')] do
|
465
|
-
attributes :name
|
466
|
-
end
|
467
458
|
end
|
468
459
|
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
attributes :name
|
460
|
+
# @todo fix this
|
461
|
+
it "renders properly when a collection is the named root node" do
|
462
|
+
nodes = node_wrap do
|
463
|
+
collection :people => [Person.new('bert'), Person.new('ernie')] do
|
464
|
+
attributes :name
|
465
|
+
end
|
476
466
|
end
|
477
|
-
end
|
478
|
-
|
479
|
-
nodes.result.should == [{:name => 'bert'}, {:name => 'ernie'}]
|
480
|
-
end
|
481
467
|
|
482
|
-
|
483
|
-
nodes = node_wrap do
|
484
|
-
collection :people => [] do
|
485
|
-
attributes :name
|
486
|
-
end
|
468
|
+
nodes.result.should == {:people => [{:name => 'bert'}, {:name => 'ernie'}]}
|
487
469
|
end
|
488
470
|
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
collection :people => nil do
|
495
|
-
attributes :name
|
471
|
+
it "renders properly when a collection is the root node" do
|
472
|
+
nodes = node_wrap do
|
473
|
+
collection [Person.new('bert'), Person.new('ernie')] do
|
474
|
+
attributes :name
|
475
|
+
end
|
496
476
|
end
|
497
|
-
end
|
498
477
|
|
499
|
-
|
500
|
-
|
478
|
+
nodes.result.should == [{:name => 'bert'}, {:name => 'ernie'}]
|
479
|
+
end
|
501
480
|
|
502
|
-
|
503
|
-
|
504
|
-
|
481
|
+
it "gracefully handles empty collections" do
|
482
|
+
nodes = node_wrap do
|
483
|
+
collection :people => [] do
|
484
|
+
attributes :name
|
485
|
+
end
|
486
|
+
end
|
505
487
|
|
506
|
-
|
507
|
-
|
508
|
-
attributes :title
|
509
|
-
attribute(:comment_count) { |post| post.comments.count }
|
488
|
+
nodes.result.should == {:people => []}
|
489
|
+
end
|
510
490
|
|
511
|
-
|
512
|
-
|
491
|
+
it "gracefully handles nil collections" do
|
492
|
+
nodes = node_wrap do
|
493
|
+
collection :people => nil do
|
494
|
+
attributes :name
|
513
495
|
end
|
514
496
|
end
|
515
|
-
end
|
516
497
|
|
517
|
-
|
518
|
-
|
519
|
-
{:title => 'my post', :comment_count => 1, :comments => [{:body => 'my comment'}]}
|
520
|
-
]
|
521
|
-
}
|
522
|
-
end
|
498
|
+
nodes.result.should == {:people => []}
|
499
|
+
end
|
523
500
|
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
posts = [post]
|
501
|
+
it "renders nested collections properly" do
|
502
|
+
post = Post.new("my post")
|
503
|
+
post.comments << Comment.new('my comment')
|
528
504
|
|
529
|
-
|
530
|
-
|
531
|
-
|
505
|
+
nodes = node_wrap do
|
506
|
+
collection :posts => [post] do |post|
|
507
|
+
attributes :title
|
508
|
+
attribute(:comment_count) { |post| post.comments.count }
|
532
509
|
|
533
|
-
|
534
|
-
|
510
|
+
collection :comments => post.comments do
|
511
|
+
attributes :body
|
512
|
+
end
|
535
513
|
end
|
536
514
|
end
|
537
|
-
end
|
538
515
|
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
516
|
+
nodes.result.should == {
|
517
|
+
:posts => [
|
518
|
+
{:title => 'my post', :comment_count => 1, :comments => [{:body => 'my comment'}]}
|
519
|
+
]
|
520
|
+
}
|
521
|
+
end
|
545
522
|
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
post2.comments << Comment.new('post 2 first comment')
|
551
|
-
post2.comments << Comment.new('post 2 second comment')
|
523
|
+
it "renders objects nested in collections properly" do
|
524
|
+
post = Post.new 'foo'
|
525
|
+
post.author = Author.new('John Doe')
|
526
|
+
posts = [post]
|
552
527
|
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
attribute(:comment_count) { |post| post.comments.count }
|
528
|
+
nodes = node_wrap do
|
529
|
+
collection :data => posts do |post|
|
530
|
+
attributes :title
|
557
531
|
|
558
|
-
|
559
|
-
|
532
|
+
object :author => post.author do
|
533
|
+
attributes :name
|
534
|
+
end
|
560
535
|
end
|
561
536
|
end
|
537
|
+
|
538
|
+
nodes.result.should == {
|
539
|
+
:data => [
|
540
|
+
{:title => 'foo', :author => {:name => 'John Doe'}}
|
541
|
+
]
|
542
|
+
}
|
562
543
|
end
|
563
544
|
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
},
|
571
|
-
{
|
572
|
-
:title => 'post 2',
|
573
|
-
:comment_count => 2,
|
574
|
-
:comments => [{:body => 'post 2 first comment'}, {:body => 'post 2 second comment'}]
|
575
|
-
}
|
576
|
-
]
|
577
|
-
}
|
578
|
-
end
|
545
|
+
it "renders nested collections with dynamic property values correctly" do
|
546
|
+
post1 = Post.new("post 1")
|
547
|
+
post2 = Post.new("post 2")
|
548
|
+
post1.comments << Comment.new('post 1 comment')
|
549
|
+
post2.comments << Comment.new('post 2 first comment')
|
550
|
+
post2.comments << Comment.new('post 2 second comment')
|
579
551
|
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
552
|
+
nodes = node_wrap do
|
553
|
+
collection :posts => [post1, post2] do |post|
|
554
|
+
attributes :title
|
555
|
+
attribute(:comment_count) { |post| post.comments.count }
|
584
556
|
|
585
|
-
|
586
|
-
|
587
|
-
|
557
|
+
collection :comments => post.comments do
|
558
|
+
attributes :body
|
559
|
+
end
|
560
|
+
end
|
588
561
|
end
|
562
|
+
|
563
|
+
nodes.result.should == {
|
564
|
+
:posts => [
|
565
|
+
{
|
566
|
+
:title => 'post 1',
|
567
|
+
:comment_count => 1,
|
568
|
+
:comments => [{:body => 'post 1 comment'}]
|
569
|
+
},
|
570
|
+
{
|
571
|
+
:title => 'post 2',
|
572
|
+
:comment_count => 2,
|
573
|
+
:comments => [{:body => 'post 2 first comment'}, {:body => 'post 2 second comment'}]
|
574
|
+
}
|
575
|
+
]
|
576
|
+
}
|
589
577
|
end
|
590
578
|
|
591
|
-
|
592
|
-
|
579
|
+
it "allows root level attributes using local variables" do
|
580
|
+
node = node_wrap do
|
581
|
+
name = "john doe"
|
582
|
+
age = 25
|
593
583
|
|
594
|
-
|
584
|
+
object do
|
585
|
+
attribute(:name) { name }
|
586
|
+
attribute(:age) { age }
|
587
|
+
end
|
588
|
+
end
|
595
589
|
|
596
|
-
|
597
|
-
it "includes the partial as a top level" do
|
598
|
-
nodes = node_wrap do
|
599
|
-
template "spec/fixtures/partial.json.bldr"
|
590
|
+
node.result.should == {:name => 'john doe', :age => 25}
|
600
591
|
end
|
601
592
|
|
602
|
-
nodes.result.should == {:foo => "bar"}
|
603
593
|
end
|
604
|
-
|
605
|
-
it "includes the partial on a top level object" do
|
606
|
-
nodes = node_wrap do
|
607
|
-
object :container do
|
608
|
-
attribute(:blah) { "baz" }
|
609
|
-
template "spec/fixtures/partial.json.bldr"
|
610
|
-
end
|
611
|
-
end
|
612
594
|
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
it "includes the partial on a top level collection" do
|
617
|
-
nodes = node_wrap do
|
618
|
-
collection :people => [Person.new('bert'), Person.new('ernie')] do
|
619
|
-
attribute(:blah) { "baz" }
|
595
|
+
describe Node, "#template" do
|
596
|
+
it "includes the partial as a top level" do
|
597
|
+
nodes = node_wrap do
|
620
598
|
template "spec/fixtures/partial.json.bldr"
|
621
599
|
end
|
600
|
+
|
601
|
+
nodes.result.should == {:foo => "bar"}
|
622
602
|
end
|
623
603
|
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
it "includes the partial on a sub object" do
|
628
|
-
nodes = node_wrap do
|
629
|
-
object :container do
|
630
|
-
object :sub do
|
604
|
+
it "includes the partial on a top level object" do
|
605
|
+
nodes = node_wrap do
|
606
|
+
object :container do
|
631
607
|
attribute(:blah) { "baz" }
|
632
608
|
template "spec/fixtures/partial.json.bldr"
|
633
609
|
end
|
634
610
|
end
|
611
|
+
|
612
|
+
nodes.result.should == {:container => {:blah => "baz", :foo => "bar"}}
|
635
613
|
end
|
636
614
|
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
it "includes the partial on a sub collection" do
|
641
|
-
nodes = node_wrap do
|
642
|
-
object :container do
|
615
|
+
it "includes the partial on a top level collection" do
|
616
|
+
nodes = node_wrap do
|
643
617
|
collection :people => [Person.new('bert'), Person.new('ernie')] do
|
644
618
|
attribute(:blah) { "baz" }
|
645
619
|
template "spec/fixtures/partial.json.bldr"
|
646
620
|
end
|
647
621
|
end
|
622
|
+
|
623
|
+
nodes.result.should == {:people => [{:blah => "baz", :foo => 'bar'}, {:blah => "baz", :foo => 'bar'}]}
|
648
624
|
end
|
649
625
|
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
object :sub do
|
658
|
-
attribute(:blah) { "baz" }
|
659
|
-
template "spec/fixtures/partial.json.bldr"
|
626
|
+
it "includes the partial on a sub object" do
|
627
|
+
nodes = node_wrap do
|
628
|
+
object :container do
|
629
|
+
object :sub do
|
630
|
+
attribute(:blah) { "baz" }
|
631
|
+
template "spec/fixtures/partial.json.bldr"
|
632
|
+
end
|
660
633
|
end
|
661
634
|
end
|
635
|
+
|
636
|
+
nodes.result.should == {:container => {:sub => {:blah => "baz", :foo => "bar"}}}
|
662
637
|
end
|
663
638
|
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
639
|
+
it "includes the partial on a sub collection" do
|
640
|
+
nodes = node_wrap do
|
641
|
+
object :container do
|
642
|
+
collection :people => [Person.new('bert'), Person.new('ernie')] do
|
643
|
+
attribute(:blah) { "baz" }
|
644
|
+
template "spec/fixtures/partial.json.bldr"
|
645
|
+
end
|
646
|
+
end
|
647
|
+
end
|
648
|
+
|
649
|
+
nodes.result.should == {:container => {:people => [{:blah => "baz", :foo => 'bar'}, {:blah => "baz", :foo => 'bar'}]}}
|
671
650
|
end
|
672
651
|
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
652
|
+
it "includes both the partials" do
|
653
|
+
nodes = node_wrap do
|
654
|
+
object :container do
|
655
|
+
template "spec/fixtures/partial.json.bldr"
|
656
|
+
object :sub do
|
657
|
+
attribute(:blah) { "baz" }
|
658
|
+
template "spec/fixtures/partial.json.bldr"
|
659
|
+
end
|
660
|
+
end
|
661
|
+
end
|
662
|
+
|
663
|
+
nodes.result.should == {:container => {:foo => "bar", :sub => {:blah => "baz", :foo => "bar"}}}
|
664
|
+
end
|
665
|
+
|
666
|
+
it "includes the partial with the locals" do
|
667
|
+
Obj = Struct.new(:foo)
|
678
668
|
nodes = node_wrap do
|
679
|
-
template "
|
669
|
+
template "spec/fixtures/partial_with_locals.json.bldr", :locals => {:obj => Obj.new('test')}
|
680
670
|
end
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
671
|
+
|
672
|
+
nodes.result.should == {:name => {:foo => 'test'}}
|
673
|
+
end
|
674
|
+
|
675
|
+
it "raises an error when the partial isn't found" do
|
676
|
+
expect {
|
677
|
+
nodes = node_wrap do
|
678
|
+
template "unknown/path"
|
679
|
+
end
|
680
|
+
}.to raise_error(Errno::ENOENT)
|
681
|
+
end
|
682
|
+
|
683
|
+
it "doesn't raise an error when with a base path option specified and the right file" do
|
684
|
+
nodes = node_wrap nil, :views => 'spec/fixtures/some' do
|
685
|
+
object :foo do
|
686
|
+
template "include"
|
687
|
+
end
|
688
688
|
end
|
689
689
|
end
|
690
690
|
end
|
691
|
-
end
|
692
691
|
|
693
|
-
describe "
|
694
|
-
|
695
|
-
|
692
|
+
describe Node, "#locals" do
|
693
|
+
let(:node) { Bldr::Node.new({:foo => 'bar'}, :locals => {:key => 'val'})}
|
694
|
+
subject { node.locals }
|
696
695
|
|
697
|
-
|
696
|
+
it { should == {:key => 'val'} }
|
697
|
+
end
|
698
|
+
|
699
|
+
describe Node, '#current_object' do
|
700
|
+
it 'returns the node value' do
|
701
|
+
Node.new('hey').current_object.should == 'hey'
|
702
|
+
end
|
703
|
+
|
704
|
+
it 'displays a deprecation warning' do
|
705
|
+
Object.any_instance.should_receive(:warn).with("[DEPRECATION] `current_object` is deprecated. Please use object or collection block varibles instead.")
|
706
|
+
Node.new.current_object
|
707
|
+
end
|
708
|
+
end
|
698
709
|
end
|