jbuilder 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -0
- data/Gemfile.lock +3 -3
- data/Rakefile +10 -0
- data/jbuilder.gemspec +1 -2
- data/lib/jbuilder.rb +50 -67
- data/lib/jbuilder_template.rb +1 -11
- data/test/jbuilder_template_test.rb +38 -21
- data/test/jbuilder_test.rb +84 -67
- metadata +6 -26
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,9 +1,8 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
jbuilder (0.
|
4
|
+
jbuilder (0.6.0)
|
5
5
|
activesupport (>= 3.0.0)
|
6
|
-
blankslate (>= 2.1.2.4)
|
7
6
|
|
8
7
|
GEM
|
9
8
|
remote: http://rubygems.org/
|
@@ -24,7 +23,6 @@ GEM
|
|
24
23
|
activesupport (3.2.8)
|
25
24
|
i18n (~> 0.6)
|
26
25
|
multi_json (~> 1.0)
|
27
|
-
blankslate (2.1.2.4)
|
28
26
|
builder (3.0.0)
|
29
27
|
erubis (2.7.0)
|
30
28
|
hike (1.2.1)
|
@@ -36,6 +34,7 @@ GEM
|
|
36
34
|
rack (>= 0.4)
|
37
35
|
rack-test (0.6.1)
|
38
36
|
rack (>= 1.0)
|
37
|
+
rake (0.9.2.2)
|
39
38
|
sprockets (2.1.3)
|
40
39
|
hike (~> 1.2)
|
41
40
|
rack (~> 1.0)
|
@@ -48,3 +47,4 @@ PLATFORMS
|
|
48
47
|
DEPENDENCIES
|
49
48
|
actionpack
|
50
49
|
jbuilder!
|
50
|
+
rake
|
data/Rakefile
ADDED
data/jbuilder.gemspec
CHANGED
@@ -1,12 +1,11 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'jbuilder'
|
3
|
-
s.version = '0.
|
3
|
+
s.version = '0.6.0'
|
4
4
|
s.author = 'David Heinemeier Hansson'
|
5
5
|
s.email = 'david@37signals.com'
|
6
6
|
s.summary = 'Create JSON structures via a Builder-style DSL'
|
7
7
|
|
8
8
|
s.add_dependency 'activesupport', '>= 3.0.0'
|
9
|
-
s.add_dependency 'blankslate', '>= 2.1.2.4'
|
10
9
|
|
11
10
|
s.files = Dir["#{File.dirname(__FILE__)}/**/*"]
|
12
11
|
end
|
data/lib/jbuilder.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
|
-
require '
|
1
|
+
require 'active_support/basic_object'
|
2
2
|
require 'active_support/ordered_hash'
|
3
3
|
require 'active_support/core_ext/array/access'
|
4
4
|
require 'active_support/core_ext/enumerable'
|
5
5
|
require 'active_support/json'
|
6
6
|
require 'multi_json'
|
7
|
-
|
7
|
+
|
8
|
+
class Jbuilder < ActiveSupport::BasicObject
|
8
9
|
class KeyFormatter
|
9
10
|
def initialize(*args)
|
10
11
|
@format = {}
|
@@ -34,20 +35,18 @@ class Jbuilder < BlankSlate
|
|
34
35
|
end
|
35
36
|
end
|
36
37
|
end
|
37
|
-
|
38
|
+
|
38
39
|
# Yields a builder and automatically turns the result into a JSON string
|
39
|
-
def self.encode
|
40
|
-
|
40
|
+
def self.encode(*args)
|
41
|
+
jbuilder = new(*args)
|
42
|
+
yield jbuilder
|
43
|
+
jbuilder.target!
|
41
44
|
end
|
42
45
|
|
43
46
|
@@key_formatter = KeyFormatter.new
|
44
47
|
|
45
|
-
define_method(:__class__, find_hidden_method(:class))
|
46
|
-
define_method(:_tap, find_hidden_method(:tap))
|
47
|
-
reveal(:respond_to?)
|
48
|
-
|
49
48
|
def initialize(key_formatter = @@key_formatter.clone)
|
50
|
-
@attributes = ActiveSupport::OrderedHash.new
|
49
|
+
@attributes = ::ActiveSupport::OrderedHash.new
|
51
50
|
@key_formatter = key_formatter
|
52
51
|
end
|
53
52
|
|
@@ -68,8 +67,8 @@ class Jbuilder < BlankSlate
|
|
68
67
|
#
|
69
68
|
# { "author": { "name": "David", "age": 32 } }
|
70
69
|
def set!(key, value = nil)
|
71
|
-
if block_given?
|
72
|
-
|
70
|
+
if ::Kernel::block_given?
|
71
|
+
_set_value(key, _with_attributes { yield self })
|
73
72
|
else
|
74
73
|
_set_value(key, value)
|
75
74
|
end
|
@@ -106,7 +105,7 @@ class Jbuilder < BlankSlate
|
|
106
105
|
def key_format!(*args)
|
107
106
|
@key_formatter = KeyFormatter.new(*args)
|
108
107
|
end
|
109
|
-
|
108
|
+
|
110
109
|
# Same as the instance method key_format! except sets the default.
|
111
110
|
def self.key_format(*args)
|
112
111
|
@@key_formatter = KeyFormatter.new(*args)
|
@@ -127,13 +126,13 @@ class Jbuilder < BlankSlate
|
|
127
126
|
#
|
128
127
|
# json.comments(@post.comments) do |json, comment|
|
129
128
|
# json.content comment.formatted_content
|
130
|
-
# end
|
129
|
+
# end
|
131
130
|
def child!
|
132
|
-
@attributes = [] unless @attributes.is_a? Array
|
133
|
-
@attributes <<
|
131
|
+
@attributes = [] unless @attributes.is_a? ::Array
|
132
|
+
@attributes << _with_attributes { yield self }
|
134
133
|
end
|
135
134
|
|
136
|
-
# Turns the current element into an array and iterates over the passed collection, adding each iteration as
|
135
|
+
# Turns the current element into an array and iterates over the passed collection, adding each iteration as
|
137
136
|
# an element of the resulting array.
|
138
137
|
#
|
139
138
|
# Example:
|
@@ -154,14 +153,11 @@ class Jbuilder < BlankSlate
|
|
154
153
|
# json.people(@people) do |json, person|
|
155
154
|
# json.name person.name
|
156
155
|
# json.age calculate_age(person.birthday)
|
157
|
-
# end
|
156
|
+
# end
|
158
157
|
#
|
159
158
|
# { "people": [ { "name": David", "age": 32 }, { "name": Jamie", "age": 31 } ] }
|
160
159
|
def array!(collection)
|
161
|
-
@attributes =
|
162
|
-
collection.each do |element| #[] and return if collection.empty?
|
163
|
-
@attributes << _new_instance._tap { |jbuilder| yield jbuilder, element }.attributes!
|
164
|
-
end
|
160
|
+
@attributes = _map_collection(collection) { |element| yield self, element }
|
165
161
|
end
|
166
162
|
|
167
163
|
# Extracts the mentioned attributes or hash elements from the passed object and turns them into attributes of the JSON.
|
@@ -182,20 +178,18 @@ class Jbuilder < BlankSlate
|
|
182
178
|
#
|
183
179
|
# json.(@person, :name, :age)
|
184
180
|
def extract!(object, *attributes)
|
185
|
-
if object.is_a?(Hash)
|
181
|
+
if object.is_a?(::Hash)
|
186
182
|
attributes.each {|attribute| _set_value attribute, object.send(:fetch, attribute)}
|
187
183
|
else
|
188
184
|
attributes.each {|attribute| _set_value attribute, object.send(attribute)}
|
189
185
|
end
|
190
186
|
end
|
191
187
|
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
extract!(object, *attributes)
|
198
|
-
end
|
188
|
+
def call(object = nil, *attributes)
|
189
|
+
if attributes.empty?
|
190
|
+
array!(object) { |_, element| yield self, element }
|
191
|
+
else
|
192
|
+
extract!(object, *attributes)
|
199
193
|
end
|
200
194
|
end
|
201
195
|
|
@@ -203,10 +197,10 @@ class Jbuilder < BlankSlate
|
|
203
197
|
def attributes!
|
204
198
|
@attributes
|
205
199
|
end
|
206
|
-
|
200
|
+
|
207
201
|
# Encodes the current builder as JSON.
|
208
202
|
def target!
|
209
|
-
MultiJson.encode @attributes
|
203
|
+
::MultiJson.encode @attributes
|
210
204
|
end
|
211
205
|
|
212
206
|
|
@@ -218,71 +212,60 @@ class Jbuilder < BlankSlate
|
|
218
212
|
|
219
213
|
private
|
220
214
|
def method_missing(method, value = nil, *args)
|
221
|
-
if block_given?
|
215
|
+
result = if ::Kernel.block_given?
|
222
216
|
if value
|
223
217
|
# json.comments @post.comments { |json, comment| ... }
|
224
218
|
# { "comments": [ { ... }, { ... } ] }
|
225
|
-
|
219
|
+
_map_collection(value) { |element| yield self, element }
|
226
220
|
else
|
227
221
|
# json.comments { |json| ... }
|
228
222
|
# { "comments": ... }
|
229
|
-
|
223
|
+
_with_attributes { yield self }
|
230
224
|
end
|
231
225
|
else
|
232
226
|
if args.empty?
|
233
|
-
if Jbuilder === value
|
227
|
+
if ::Jbuilder === value
|
234
228
|
# json.age 32
|
235
229
|
# json.person another_jbuilder
|
236
230
|
# { "age": 32, "person": { ... }
|
237
|
-
|
231
|
+
value.attributes!
|
238
232
|
else
|
239
233
|
# json.age 32
|
240
234
|
# { "age": 32 }
|
241
|
-
|
235
|
+
value
|
242
236
|
end
|
243
237
|
else
|
244
238
|
if value.respond_to?(:each)
|
245
239
|
# json.comments(@post.comments, :content, :created_at)
|
246
240
|
# { "comments": [ { "content": "hello", "created_at": "..." }, { "content": "world", "created_at": "..." } ] }
|
247
|
-
|
241
|
+
_map_collection(value) do |element|
|
242
|
+
args.each do |attribute|
|
243
|
+
_set_value attribute, element.send(attribute)
|
244
|
+
end
|
245
|
+
end
|
248
246
|
else
|
249
247
|
# json.author @post.creator, :name, :email_address
|
250
248
|
# { "author": { "name": "David", "email_address": "david@loudthinking.com" } }
|
251
|
-
|
249
|
+
_with_attributes { extract! value, *args }
|
252
250
|
end
|
253
251
|
end
|
254
252
|
end
|
253
|
+
_set_value method, result
|
255
254
|
end
|
256
255
|
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
end
|
261
|
-
|
262
|
-
def _yield_nesting(container)
|
263
|
-
_set_value container, _new_instance._tap { |jbuilder| yield jbuilder }.attributes!
|
264
|
-
end
|
265
|
-
|
266
|
-
def _inline_nesting(container, collection, attributes)
|
267
|
-
_yield_nesting(container) do |parent|
|
268
|
-
parent.array!(collection) do |child, element|
|
269
|
-
attributes.each do |attribute|
|
270
|
-
child._set_value attribute, element.send(attribute)
|
271
|
-
end
|
272
|
-
end
|
256
|
+
def _map_collection(collection)
|
257
|
+
collection.each.map do |element|
|
258
|
+
_with_attributes { yield element }
|
273
259
|
end
|
274
260
|
end
|
275
|
-
|
276
|
-
def
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
def _inline_extract(container, record, attributes)
|
285
|
-
_yield_nesting(container) { |parent| parent.extract! record, *attributes }
|
261
|
+
|
262
|
+
def _with_attributes
|
263
|
+
parent_attributes, parent_formatter = @attributes, @key_formatter
|
264
|
+
@attributes = ::ActiveSupport::OrderedHash.new
|
265
|
+
yield
|
266
|
+
@attributes
|
267
|
+
ensure
|
268
|
+
@attributes, @key_formatter = parent_attributes, parent_formatter
|
286
269
|
end
|
287
270
|
end
|
288
271
|
|
data/lib/jbuilder_template.rb
CHANGED
@@ -1,8 +1,4 @@
|
|
1
1
|
class JbuilderTemplate < Jbuilder
|
2
|
-
def self.encode(context)
|
3
|
-
new(context)._tap { |jbuilder| yield jbuilder }.target!
|
4
|
-
end
|
5
|
-
|
6
2
|
def initialize(context, *args)
|
7
3
|
@context = context
|
8
4
|
super(*args)
|
@@ -10,7 +6,7 @@ class JbuilderTemplate < Jbuilder
|
|
10
6
|
|
11
7
|
def partial!(options, locals = {})
|
12
8
|
case options
|
13
|
-
when Hash
|
9
|
+
when ::Hash
|
14
10
|
options[:locals] ||= {}
|
15
11
|
options[:locals].merge!(:json => self)
|
16
12
|
@context.render(options)
|
@@ -18,11 +14,6 @@ class JbuilderTemplate < Jbuilder
|
|
18
14
|
@context.render(options, locals.merge(:json => self))
|
19
15
|
end
|
20
16
|
end
|
21
|
-
|
22
|
-
private
|
23
|
-
def _new_instance
|
24
|
-
__class__.new(@context, @key_formatter)
|
25
|
-
end
|
26
17
|
end
|
27
18
|
|
28
19
|
class JbuilderHandler
|
@@ -30,7 +21,6 @@ class JbuilderHandler
|
|
30
21
|
self.default_format = Mime::JSON
|
31
22
|
|
32
23
|
def self.call(template)
|
33
|
-
|
34
24
|
# this juggling is required to keep line numbers right in the error
|
35
25
|
%{__already_defined = defined?(json); json||=JbuilderTemplate.new(self); #{template.source}
|
36
26
|
json.target! unless __already_defined}
|
@@ -1,39 +1,56 @@
|
|
1
1
|
require 'test/unit'
|
2
|
-
require 'active_support/test_case'
|
3
|
-
require 'active_support/inflector'
|
4
|
-
require 'action_dispatch'
|
5
2
|
require 'action_view'
|
3
|
+
require 'action_view/testing/resolvers'
|
6
4
|
|
7
5
|
require 'jbuilder'
|
8
|
-
require 'jbuilder_template'
|
9
6
|
|
10
|
-
class JbuilderTemplateTest <
|
7
|
+
class JbuilderTemplateTest < ActionView::TestCase
|
8
|
+
def partials
|
9
|
+
{ "_partial.json.jbuilder" => 'json.content "hello"' }
|
10
|
+
end
|
11
|
+
|
12
|
+
def render_jbuilder(source)
|
13
|
+
@rendered = []
|
14
|
+
lookup_context.view_paths = [ActionView::FixtureResolver.new(partials.merge("test.json.jbuilder" => source))]
|
15
|
+
ActionView::Template.new(source, "test", JbuilderHandler, :virtual_path => "test").render(self, {}).strip
|
16
|
+
end
|
17
|
+
|
11
18
|
test "rendering" do
|
12
|
-
json =
|
19
|
+
json = render_jbuilder <<-JBUILDER
|
13
20
|
json.content "hello"
|
14
|
-
|
15
|
-
|
16
|
-
assert_equal "hello",
|
21
|
+
JBUILDER
|
22
|
+
|
23
|
+
assert_equal "hello", MultiJson.load(json)["content"]
|
17
24
|
end
|
18
25
|
|
19
26
|
test "key_format! with parameter" do
|
20
|
-
json =
|
21
|
-
|
22
|
-
|
27
|
+
json = render_jbuilder <<-JBUILDER
|
28
|
+
json.key_format! :camelize => [:lower]
|
29
|
+
json.camel_style "for JS"
|
30
|
+
JBUILDER
|
23
31
|
|
24
|
-
assert_equal ['camelStyle'], json.
|
32
|
+
assert_equal ['camelStyle'], MultiJson.load(json).keys
|
25
33
|
end
|
26
34
|
|
27
35
|
test "key_format! propagates to child elements" do
|
28
|
-
json =
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
+
json = render_jbuilder <<-JBUILDER
|
37
|
+
json.key_format! :upcase
|
38
|
+
json.level1 "one"
|
39
|
+
json.level2 do |json|
|
40
|
+
json.value "two"
|
41
|
+
end
|
42
|
+
JBUILDER
|
43
|
+
|
44
|
+
result = MultiJson.load(json)
|
36
45
|
assert_equal "one", result["LEVEL1"]
|
37
46
|
assert_equal "two", result["LEVEL2"]["VALUE"]
|
38
47
|
end
|
48
|
+
|
49
|
+
test "partial! renders partial" do
|
50
|
+
json = render_jbuilder <<-JBUILDER
|
51
|
+
json.partial! 'partial'
|
52
|
+
JBUILDER
|
53
|
+
|
54
|
+
assert_equal "hello", MultiJson.load(json)["content"]
|
55
|
+
end
|
39
56
|
end
|
data/test/jbuilder_test.rb
CHANGED
@@ -9,8 +9,8 @@ class JbuilderTest < ActiveSupport::TestCase
|
|
9
9
|
json = Jbuilder.encode do |json|
|
10
10
|
json.content "hello"
|
11
11
|
end
|
12
|
-
|
13
|
-
assert_equal "hello",
|
12
|
+
|
13
|
+
assert_equal "hello", MultiJson.load(json)["content"]
|
14
14
|
end
|
15
15
|
|
16
16
|
test "single key with false value" do
|
@@ -18,7 +18,7 @@ class JbuilderTest < ActiveSupport::TestCase
|
|
18
18
|
json.content false
|
19
19
|
end
|
20
20
|
|
21
|
-
assert_equal false,
|
21
|
+
assert_equal false, MultiJson.load(json)["content"]
|
22
22
|
end
|
23
23
|
|
24
24
|
test "single key with nil value" do
|
@@ -26,8 +26,8 @@ class JbuilderTest < ActiveSupport::TestCase
|
|
26
26
|
json.content nil
|
27
27
|
end
|
28
28
|
|
29
|
-
assert
|
30
|
-
assert_equal nil,
|
29
|
+
assert MultiJson.load(json).has_key?("content")
|
30
|
+
assert_equal nil, MultiJson.load(json)["content"]
|
31
31
|
end
|
32
32
|
|
33
33
|
test "multiple keys" do
|
@@ -35,34 +35,38 @@ class JbuilderTest < ActiveSupport::TestCase
|
|
35
35
|
json.title "hello"
|
36
36
|
json.content "world"
|
37
37
|
end
|
38
|
-
|
39
|
-
|
38
|
+
|
39
|
+
MultiJson.load(json).tap do |parsed|
|
40
40
|
assert_equal "hello", parsed["title"]
|
41
41
|
assert_equal "world", parsed["content"]
|
42
42
|
end
|
43
43
|
end
|
44
|
-
|
44
|
+
|
45
45
|
test "extracting from object" do
|
46
46
|
person = Struct.new(:name, :age).new("David", 32)
|
47
|
-
|
47
|
+
|
48
48
|
json = Jbuilder.encode do |json|
|
49
49
|
json.extract! person, :name, :age
|
50
50
|
end
|
51
|
-
|
52
|
-
|
51
|
+
|
52
|
+
MultiJson.load(json).tap do |parsed|
|
53
53
|
assert_equal "David", parsed["name"]
|
54
54
|
assert_equal 32, parsed["age"]
|
55
55
|
end
|
56
56
|
end
|
57
|
-
|
57
|
+
|
58
58
|
test "extracting from object using call style for 1.9" do
|
59
59
|
person = Struct.new(:name, :age).new("David", 32)
|
60
|
-
|
60
|
+
|
61
61
|
json = Jbuilder.encode do |json|
|
62
|
-
|
62
|
+
if ::RUBY_VERSION > '1.9'
|
63
|
+
instance_eval "json.(person, :name, :age)"
|
64
|
+
else
|
65
|
+
instance_eval "json.call(person, :name, :age)"
|
66
|
+
end
|
63
67
|
end
|
64
|
-
|
65
|
-
|
68
|
+
|
69
|
+
MultiJson.load(json).tap do |parsed|
|
66
70
|
assert_equal "David", parsed["name"]
|
67
71
|
assert_equal 32, parsed["age"]
|
68
72
|
end
|
@@ -75,7 +79,7 @@ class JbuilderTest < ActiveSupport::TestCase
|
|
75
79
|
json.extract! person, :name, :age
|
76
80
|
end
|
77
81
|
|
78
|
-
|
82
|
+
MultiJson.load(json).tap do |parsed|
|
79
83
|
assert_equal "Jim", parsed["name"]
|
80
84
|
assert_equal 34, parsed["age"]
|
81
85
|
end
|
@@ -88,13 +92,13 @@ class JbuilderTest < ActiveSupport::TestCase
|
|
88
92
|
json.age 32
|
89
93
|
end
|
90
94
|
end
|
91
|
-
|
92
|
-
|
95
|
+
|
96
|
+
MultiJson.load(json).tap do |parsed|
|
93
97
|
assert_equal "David", parsed["author"]["name"]
|
94
98
|
assert_equal 32, parsed["author"]["age"]
|
95
99
|
end
|
96
100
|
end
|
97
|
-
|
101
|
+
|
98
102
|
test "nesting multiple children with block" do
|
99
103
|
json = Jbuilder.encode do |json|
|
100
104
|
json.comments do |json|
|
@@ -103,69 +107,69 @@ class JbuilderTest < ActiveSupport::TestCase
|
|
103
107
|
end
|
104
108
|
end
|
105
109
|
|
106
|
-
|
110
|
+
MultiJson.load(json).tap do |parsed|
|
107
111
|
assert_equal "hello", parsed["comments"].first["content"]
|
108
112
|
assert_equal "world", parsed["comments"].second["content"]
|
109
113
|
end
|
110
114
|
end
|
111
|
-
|
115
|
+
|
112
116
|
test "nesting single child with inline extract" do
|
113
117
|
person = Class.new do
|
114
118
|
attr_reader :name, :age
|
115
|
-
|
119
|
+
|
116
120
|
def initialize(name, age)
|
117
121
|
@name, @age = name, age
|
118
122
|
end
|
119
123
|
end.new("David", 32)
|
120
|
-
|
124
|
+
|
121
125
|
json = Jbuilder.encode do |json|
|
122
126
|
json.author person, :name, :age
|
123
127
|
end
|
124
|
-
|
125
|
-
|
128
|
+
|
129
|
+
MultiJson.load(json).tap do |parsed|
|
126
130
|
assert_equal "David", parsed["author"]["name"]
|
127
131
|
assert_equal 32, parsed["author"]["age"]
|
128
132
|
end
|
129
133
|
end
|
130
|
-
|
134
|
+
|
131
135
|
test "nesting multiple children from array" do
|
132
136
|
comments = [ Struct.new(:content, :id).new("hello", 1), Struct.new(:content, :id).new("world", 2) ]
|
133
|
-
|
137
|
+
|
134
138
|
json = Jbuilder.encode do |json|
|
135
139
|
json.comments comments, :content
|
136
140
|
end
|
137
|
-
|
138
|
-
|
141
|
+
|
142
|
+
MultiJson.load(json).tap do |parsed|
|
139
143
|
assert_equal ["content"], parsed["comments"].first.keys
|
140
144
|
assert_equal "hello", parsed["comments"].first["content"]
|
141
145
|
assert_equal "world", parsed["comments"].second["content"]
|
142
146
|
end
|
143
147
|
end
|
144
|
-
|
148
|
+
|
145
149
|
test "nesting multiple children from array when child array is empty" do
|
146
150
|
comments = []
|
147
|
-
|
151
|
+
|
148
152
|
json = Jbuilder.encode do |json|
|
149
153
|
json.name "Parent"
|
150
154
|
json.comments comments, :content
|
151
155
|
end
|
152
|
-
|
153
|
-
|
156
|
+
|
157
|
+
MultiJson.load(json).tap do |parsed|
|
154
158
|
assert_equal "Parent", parsed["name"]
|
155
159
|
assert_equal [], parsed["comments"]
|
156
160
|
end
|
157
161
|
end
|
158
|
-
|
162
|
+
|
159
163
|
test "nesting multiple children from array with inline loop" do
|
160
164
|
comments = [ Struct.new(:content, :id).new("hello", 1), Struct.new(:content, :id).new("world", 2) ]
|
161
|
-
|
165
|
+
|
162
166
|
json = Jbuilder.encode do |json|
|
163
167
|
json.comments comments do |json, comment|
|
164
168
|
json.content comment.content
|
165
169
|
end
|
166
170
|
end
|
167
|
-
|
168
|
-
|
171
|
+
|
172
|
+
MultiJson.load(json).tap do |parsed|
|
169
173
|
assert_equal ["content"], parsed["comments"].first.keys
|
170
174
|
assert_equal "hello", parsed["comments"].first["content"]
|
171
175
|
assert_equal "world", parsed["comments"].second["content"]
|
@@ -174,42 +178,42 @@ class JbuilderTest < ActiveSupport::TestCase
|
|
174
178
|
|
175
179
|
test "nesting multiple children from array with inline loop on root" do
|
176
180
|
comments = [ Struct.new(:content, :id).new("hello", 1), Struct.new(:content, :id).new("world", 2) ]
|
177
|
-
|
181
|
+
|
178
182
|
json = Jbuilder.encode do |json|
|
179
|
-
json.(comments) do |json, comment|
|
183
|
+
json.call(comments) do |json, comment|
|
180
184
|
json.content comment.content
|
181
185
|
end
|
182
186
|
end
|
183
|
-
|
184
|
-
|
187
|
+
|
188
|
+
MultiJson.load(json).tap do |parsed|
|
185
189
|
assert_equal "hello", parsed.first["content"]
|
186
190
|
assert_equal "world", parsed.second["content"]
|
187
191
|
end
|
188
192
|
end
|
189
|
-
|
193
|
+
|
190
194
|
test "array nested inside nested hash" do
|
191
195
|
json = Jbuilder.encode do |json|
|
192
196
|
json.author do |json|
|
193
197
|
json.name "David"
|
194
198
|
json.age 32
|
195
|
-
|
199
|
+
|
196
200
|
json.comments do |json|
|
197
201
|
json.child! { |json| json.content "hello" }
|
198
202
|
json.child! { |json| json.content "world" }
|
199
203
|
end
|
200
204
|
end
|
201
205
|
end
|
202
|
-
|
203
|
-
|
206
|
+
|
207
|
+
MultiJson.load(json).tap do |parsed|
|
204
208
|
assert_equal "hello", parsed["author"]["comments"].first["content"]
|
205
209
|
assert_equal "world", parsed["author"]["comments"].second["content"]
|
206
210
|
end
|
207
211
|
end
|
208
|
-
|
212
|
+
|
209
213
|
test "array nested inside array" do
|
210
214
|
json = Jbuilder.encode do |json|
|
211
215
|
json.comments do |json|
|
212
|
-
json.child! do |json|
|
216
|
+
json.child! do |json|
|
213
217
|
json.authors do |json|
|
214
218
|
json.child! do |json|
|
215
219
|
json.name "david"
|
@@ -218,8 +222,8 @@ class JbuilderTest < ActiveSupport::TestCase
|
|
218
222
|
end
|
219
223
|
end
|
220
224
|
end
|
221
|
-
|
222
|
-
assert_equal "david",
|
225
|
+
|
226
|
+
assert_equal "david", MultiJson.load(json)["comments"].first["authors"].first["name"]
|
223
227
|
end
|
224
228
|
|
225
229
|
test "nested jbuilder objects" do
|
@@ -229,7 +233,7 @@ class JbuilderTest < ActiveSupport::TestCase
|
|
229
233
|
json.value "Test"
|
230
234
|
json.nested to_nest
|
231
235
|
end
|
232
|
-
parsed =
|
236
|
+
parsed = MultiJson.load(json)
|
233
237
|
assert_equal "Test", parsed['value']
|
234
238
|
assert_equal "Nested Test", parsed["nested"]["nested_value"]
|
235
239
|
end
|
@@ -242,31 +246,31 @@ class JbuilderTest < ActiveSupport::TestCase
|
|
242
246
|
json.content comment.content
|
243
247
|
end
|
244
248
|
end
|
245
|
-
|
246
|
-
|
249
|
+
|
250
|
+
MultiJson.load(json).tap do |parsed|
|
247
251
|
assert_equal "hello", parsed.first["content"]
|
248
252
|
assert_equal "world", parsed.second["content"]
|
249
253
|
end
|
250
|
-
end
|
251
|
-
|
254
|
+
end
|
255
|
+
|
252
256
|
test "empty top-level array" do
|
253
257
|
comments = []
|
254
|
-
|
258
|
+
|
255
259
|
json = Jbuilder.encode do |json|
|
256
260
|
json.array!(comments) do |json, comment|
|
257
261
|
json.content comment.content
|
258
262
|
end
|
259
263
|
end
|
260
|
-
|
261
|
-
assert_equal [],
|
264
|
+
|
265
|
+
assert_equal [], MultiJson.load(json)
|
262
266
|
end
|
263
|
-
|
267
|
+
|
264
268
|
test "dynamically set a key/value" do
|
265
269
|
json = Jbuilder.encode do |json|
|
266
270
|
json.set!(:each, "stuff")
|
267
271
|
end
|
268
|
-
|
269
|
-
assert_equal "stuff",
|
272
|
+
|
273
|
+
assert_equal "stuff", MultiJson.load(json)["each"]
|
270
274
|
end
|
271
275
|
|
272
276
|
test "dynamically set a key/nested child with block" do
|
@@ -276,8 +280,8 @@ class JbuilderTest < ActiveSupport::TestCase
|
|
276
280
|
json.age 32
|
277
281
|
end
|
278
282
|
end
|
279
|
-
|
280
|
-
|
283
|
+
|
284
|
+
MultiJson.load(json).tap do |parsed|
|
281
285
|
assert_equal "David", parsed["author"]["name"]
|
282
286
|
assert_equal 32, parsed["author"]["age"]
|
283
287
|
end
|
@@ -304,7 +308,7 @@ class JbuilderTest < ActiveSupport::TestCase
|
|
304
308
|
json.relations RelationMock.new, :name, :age
|
305
309
|
end
|
306
310
|
|
307
|
-
parsed =
|
311
|
+
parsed = MultiJson.load(result)
|
308
312
|
assert_equal 2, parsed["relations"].length
|
309
313
|
assert_equal "Bob", parsed["relations"][0]["name"]
|
310
314
|
assert_equal 50, parsed["relations"][1]["age"]
|
@@ -339,6 +343,19 @@ class JbuilderTest < ActiveSupport::TestCase
|
|
339
343
|
assert_equal "two", result["LEVEL2"]["VALUE"]
|
340
344
|
end
|
341
345
|
|
346
|
+
test "key_format! resets after child element" do
|
347
|
+
json = Jbuilder.new
|
348
|
+
json.level2 do |json|
|
349
|
+
json.key_format! :upcase
|
350
|
+
json.value "two"
|
351
|
+
end
|
352
|
+
json.level1 "one"
|
353
|
+
|
354
|
+
result = json.attributes!
|
355
|
+
assert_equal "two", result["level2"]["VALUE"]
|
356
|
+
assert_equal "one", result["level1"]
|
357
|
+
end
|
358
|
+
|
342
359
|
test "key_format! with no parameter" do
|
343
360
|
json = Jbuilder.new
|
344
361
|
json.key_format! :upcase
|
@@ -357,7 +374,7 @@ class JbuilderTest < ActiveSupport::TestCase
|
|
357
374
|
|
358
375
|
test "key_format! with lambda/proc" do
|
359
376
|
json = Jbuilder.new
|
360
|
-
json.key_format!
|
377
|
+
json.key_format! lambda { |key| key + " and friends" }
|
361
378
|
json.oats ""
|
362
379
|
|
363
380
|
assert_equal ["oats and friends"], json.attributes!.keys
|
@@ -369,13 +386,13 @@ class JbuilderTest < ActiveSupport::TestCase
|
|
369
386
|
json.camel_style "for JS"
|
370
387
|
|
371
388
|
assert_equal ['camelStyle'], json.attributes!.keys
|
372
|
-
Jbuilder.class_variable_set
|
389
|
+
Jbuilder.send(:class_variable_set, "@@key_formatter", Jbuilder::KeyFormatter.new)
|
373
390
|
end
|
374
391
|
|
375
392
|
test "don't use default key formatter directly" do
|
376
393
|
json = Jbuilder.new
|
377
394
|
json.key "value"
|
378
395
|
|
379
|
-
assert_equal [], Jbuilder.class_variable_get
|
396
|
+
assert_equal [], Jbuilder.send(:class_variable_get, "@@key_formatter").instance_variable_get("@cache").keys
|
380
397
|
end
|
381
398
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jbuilder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-09-
|
12
|
+
date: 2012-09-21 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
16
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirement: &2152682460 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,28 +21,7 @@ dependencies:
|
|
21
21
|
version: 3.0.0
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements:
|
25
|
-
none: false
|
26
|
-
requirements:
|
27
|
-
- - ! '>='
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: 3.0.0
|
30
|
-
- !ruby/object:Gem::Dependency
|
31
|
-
name: blankslate
|
32
|
-
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
|
-
requirements:
|
35
|
-
- - ! '>='
|
36
|
-
- !ruby/object:Gem::Version
|
37
|
-
version: 2.1.2.4
|
38
|
-
type: :runtime
|
39
|
-
prerelease: false
|
40
|
-
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
|
-
requirements:
|
43
|
-
- - ! '>='
|
44
|
-
- !ruby/object:Gem::Version
|
45
|
-
version: 2.1.2.4
|
24
|
+
version_requirements: *2152682460
|
46
25
|
description:
|
47
26
|
email: david@37signals.com
|
48
27
|
executables: []
|
@@ -55,6 +34,7 @@ files:
|
|
55
34
|
- ./lib/jbuilder.rb
|
56
35
|
- ./lib/jbuilder_template.rb
|
57
36
|
- ./MIT-LICENSE
|
37
|
+
- ./Rakefile
|
58
38
|
- ./README.md
|
59
39
|
- ./test/jbuilder_template_test.rb
|
60
40
|
- ./test/jbuilder_test.rb
|
@@ -78,7 +58,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
78
58
|
version: '0'
|
79
59
|
requirements: []
|
80
60
|
rubyforge_project:
|
81
|
-
rubygems_version: 1.8.
|
61
|
+
rubygems_version: 1.8.7
|
82
62
|
signing_key:
|
83
63
|
specification_version: 3
|
84
64
|
summary: Create JSON structures via a Builder-style DSL
|