jbuilder 0.3 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +3 -0
- data/Gemfile.lock +20 -0
- data/README.md +69 -57
- data/jbuilder-0.3.gem +0 -0
- data/jbuilder.gemspec +1 -1
- data/lib/jbuilder.rb +30 -10
- data/lib/jbuilder_template.rb +1 -1
- data/test/jbuilder_test.rb +33 -0
- metadata +10 -7
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
jbuilder (0.3)
|
5
|
+
activesupport (>= 3.0.0)
|
6
|
+
blankslate (>= 2.1.2.4)
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: http://rubygems.org/
|
10
|
+
specs:
|
11
|
+
activesupport (3.1.3)
|
12
|
+
multi_json (~> 1.0)
|
13
|
+
blankslate (2.1.2.4)
|
14
|
+
multi_json (1.0.4)
|
15
|
+
|
16
|
+
PLATFORMS
|
17
|
+
ruby
|
18
|
+
|
19
|
+
DEPENDENCIES
|
20
|
+
jbuilder!
|
data/README.md
CHANGED
@@ -3,71 +3,83 @@ Jbuilder
|
|
3
3
|
|
4
4
|
Jbuilder gives you a simple DSL for declaring JSON structures that beats massaging giant hash structures. This is particularly helpful when the generation process is fraught with conditionals and loops. Here's a simple example:
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
6
|
+
``` ruby
|
7
|
+
Jbuilder.encode do |json|
|
8
|
+
json.content format_content(@message.content)
|
9
|
+
json.(@message, :created_at, :updated_at)
|
10
|
+
|
11
|
+
json.author do |json|
|
12
|
+
json.name @message.creator.name.familiar
|
13
|
+
json.email_address @message.creator.email_address_with_name
|
14
|
+
json.url url_for(@message.creator, format: :json)
|
15
|
+
end
|
16
|
+
|
17
|
+
if current_user.admin?
|
18
|
+
json.visitors calculate_visitors(@message)
|
19
|
+
end
|
20
|
+
|
21
|
+
json.comments @message.comments, :content, :created_at
|
19
22
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
end
|
23
|
+
json.attachments @message.attachments do |json, attachment|
|
24
|
+
json.filename attachment.filename
|
25
|
+
json.url url_for(attachment)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
```
|
27
29
|
|
28
30
|
This will build the following structure:
|
29
31
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
32
|
+
``` javascript
|
33
|
+
{
|
34
|
+
"content": "<p>This is <i>serious</i> monkey business",
|
35
|
+
"created_at": "2011-10-29T20:45:28-05:00",
|
36
|
+
"updated_at": "2011-10-29T20:45:28-05:00",
|
37
|
+
|
38
|
+
"author": {
|
39
|
+
"name": "David H.",
|
40
|
+
"email_address": "'David Heinemeier Hansson' <david@heinemeierhansson.com>",
|
41
|
+
"url": "http://example.com/users/1-david.json"
|
42
|
+
},
|
43
|
+
|
44
|
+
"visitors": 15,
|
45
|
+
|
46
|
+
"comments": [
|
47
|
+
{ "content": "Hello everyone!", "created_at": "2011-10-29T20:45:28-05:00" },
|
48
|
+
{ "content": "To you my good sir!", "created_at": "2011-10-29T20:47:28-05:00" }
|
49
|
+
],
|
50
|
+
|
51
|
+
"attachment": [
|
52
|
+
{ "filename": "forecast.xls", "url": "http://example.com/downloads/forecast.xls" },
|
53
|
+
{ "filename": "presentation.pdf", "url": "http://example.com/downloads/presentation.pdf" }
|
54
|
+
]
|
55
|
+
}
|
56
|
+
```
|
53
57
|
|
54
58
|
You can either use Jbuilder stand-alone or directly as an ActionView template language. When required in Rails, you can create views ala show.json.jbuilder (the json is already yielded):
|
55
59
|
|
56
|
-
|
57
|
-
|
58
|
-
|
60
|
+
``` ruby
|
61
|
+
# Any helpers available to views are available to the builder
|
62
|
+
json.content format_content(@message.content)
|
63
|
+
json.(@message, :created_at, :updated_at)
|
64
|
+
|
65
|
+
json.author do |json|
|
66
|
+
json.name @message.creator.name.familiar
|
67
|
+
json.email_address @message.creator.email_address_with_name
|
68
|
+
json.url url_for(@message.creator, format: :json)
|
69
|
+
end
|
59
70
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
json.url url_for(@message.creator, format: :json)
|
64
|
-
end
|
71
|
+
if current_user.admin?
|
72
|
+
json.visitors calculate_visitors(@message)
|
73
|
+
end
|
65
74
|
|
66
|
-
|
67
|
-
|
68
|
-
|
75
|
+
# You can use partials as well, just remember to pass in the json instance
|
76
|
+
json.partial! "api/comments/comments", @message.comments
|
77
|
+
```
|
69
78
|
|
70
|
-
|
71
|
-
json.partial! "api/comments/comments" @message.comments
|
79
|
+
Libraries similar to this in some form or another includes:
|
72
80
|
|
73
|
-
|
81
|
+
* RABL: https://github.com/nesquena/rabl
|
82
|
+
* JsonBuilder: https://github.com/nov/jsonbuilder
|
83
|
+
* JSON Builder: https://github.com/dewski/json_builder
|
84
|
+
* Jsonify: https://github.com/bsiggelkow/jsonify
|
85
|
+
* RepresentationView: https://github.com/mdub/representative_view
|
data/jbuilder-0.3.gem
ADDED
Binary file
|
data/jbuilder.gemspec
CHANGED
data/lib/jbuilder.rb
CHANGED
@@ -17,6 +17,11 @@ class Jbuilder < BlankSlate
|
|
17
17
|
@attributes = ActiveSupport::OrderedHash.new
|
18
18
|
end
|
19
19
|
|
20
|
+
# Dynamically set a key value pair.
|
21
|
+
def set!(key, value)
|
22
|
+
@attributes[key] = value
|
23
|
+
end
|
24
|
+
|
20
25
|
# Turns the current element into an array and yields a builder to add a hash.
|
21
26
|
#
|
22
27
|
# Example:
|
@@ -38,7 +43,8 @@ class Jbuilder < BlankSlate
|
|
38
43
|
@attributes << _new_instance._tap { |jbuilder| yield jbuilder }.attributes!
|
39
44
|
end
|
40
45
|
|
41
|
-
#
|
46
|
+
# Turns the current element into an array and iterates over the passed collection, adding each iteration as
|
47
|
+
# an element of the resulting array.
|
42
48
|
#
|
43
49
|
# Example:
|
44
50
|
#
|
@@ -47,7 +53,7 @@ class Jbuilder < BlankSlate
|
|
47
53
|
# json.age calculate_age(person.birthday)
|
48
54
|
# end
|
49
55
|
#
|
50
|
-
# [ { "David", 32 }, { "Jamie", 31 } ]
|
56
|
+
# [ { "name": David", "age": 32 }, { "name": Jamie", "age": 31 } ]
|
51
57
|
#
|
52
58
|
# If you are using Ruby 1.9+, you can use the call syntax instead of an explicit extract! call:
|
53
59
|
#
|
@@ -60,8 +66,10 @@ class Jbuilder < BlankSlate
|
|
60
66
|
# json.age calculate_age(person.birthday)
|
61
67
|
# end
|
62
68
|
#
|
63
|
-
# { "people": [ { "David", 32 }, { "Jamie", 31 } ] }
|
69
|
+
# { "people": [ { "name": David", "age": 32 }, { "name": Jamie", "age": 31 } ] }
|
64
70
|
def array!(collection)
|
71
|
+
@attributes = [] and return if collection.empty?
|
72
|
+
|
65
73
|
collection.each do |element|
|
66
74
|
child! do |child|
|
67
75
|
yield child, element
|
@@ -75,7 +83,7 @@ class Jbuilder < BlankSlate
|
|
75
83
|
#
|
76
84
|
# json.extract! @person, :name, :age
|
77
85
|
#
|
78
|
-
# { "David", 32 }, { "Jamie", 31 }
|
86
|
+
# { "name": David", "age": 32 }, { "name": Jamie", "age": 31 }
|
79
87
|
#
|
80
88
|
# If you are using Ruby 1.9+, you can use the call syntax instead of an explicit extract! call:
|
81
89
|
#
|
@@ -111,34 +119,46 @@ class Jbuilder < BlankSlate
|
|
111
119
|
private
|
112
120
|
def method_missing(method, *args)
|
113
121
|
case
|
122
|
+
# json.comments @post.comments { |json, comment| ... }
|
123
|
+
# { "comments": [ { ... }, { ... } ] }
|
114
124
|
when args.one? && block_given?
|
115
125
|
_yield_iteration(method, args.first) { |child, element| yield child, element }
|
126
|
+
|
127
|
+
# json.age 32
|
128
|
+
# { "age": 32 }
|
116
129
|
when args.one?
|
117
|
-
|
130
|
+
set! method, args.first
|
131
|
+
|
132
|
+
# json.comments { |json| ... }
|
133
|
+
# { "comments": ... }
|
118
134
|
when args.empty? && block_given?
|
119
135
|
_yield_nesting(method) { |jbuilder| yield jbuilder }
|
136
|
+
|
137
|
+
# json.comments(@post.comments, :content, :created_at)
|
138
|
+
# { "comments": [ { "content": "hello", "created_at": "..." }, { "content": "world", "created_at": "..." } ] }
|
120
139
|
when args.many? && args.first.is_a?(Enumerable)
|
121
140
|
_inline_nesting method, args.first, args.from(1)
|
141
|
+
|
142
|
+
# json.author @post.creator, :name, :email_address
|
143
|
+
# { "author": { "name": "David", "email_address": "david@loudthinking.com" } }
|
122
144
|
when args.many?
|
123
145
|
_inline_extract method, args.first, args.from(1)
|
124
146
|
end
|
125
147
|
end
|
126
148
|
|
127
|
-
def _assign(key, value)
|
128
|
-
@attributes[key] = value
|
129
|
-
end
|
130
|
-
|
131
149
|
# Overwrite in subclasses if you need to add initialization values
|
132
150
|
def _new_instance
|
133
151
|
__class__.new
|
134
152
|
end
|
135
153
|
|
136
154
|
def _yield_nesting(container)
|
137
|
-
|
155
|
+
set! container, _new_instance._tap { |jbuilder| yield jbuilder }.attributes!
|
138
156
|
end
|
139
157
|
|
140
158
|
def _inline_nesting(container, collection, attributes)
|
141
159
|
__send__(container) do |parent|
|
160
|
+
parent.array!(collection) and return if collection.empty?
|
161
|
+
|
142
162
|
collection.each do |element|
|
143
163
|
parent.child! do |child|
|
144
164
|
attributes.each do |attribute|
|
data/lib/jbuilder_template.rb
CHANGED
data/test/jbuilder_test.rb
CHANGED
@@ -111,6 +111,19 @@ class JbuilderTest < ActiveSupport::TestCase
|
|
111
111
|
end
|
112
112
|
end
|
113
113
|
|
114
|
+
test "nesting multiple children from array when child array is empty" do
|
115
|
+
comments = []
|
116
|
+
|
117
|
+
json = Jbuilder.encode do |json|
|
118
|
+
json.name "Parent"
|
119
|
+
json.comments comments, :content
|
120
|
+
end
|
121
|
+
|
122
|
+
JSON.parse(json).tap do |parsed|
|
123
|
+
assert_equal "Parent", parsed["name"]
|
124
|
+
assert_equal [], parsed["comments"]
|
125
|
+
end
|
126
|
+
end
|
114
127
|
|
115
128
|
test "nesting multiple children from array with inline loop" do
|
116
129
|
comments = [ Struct.new(:content, :id).new("hello", 1), Struct.new(:content, :id).new("world", 2) ]
|
@@ -192,4 +205,24 @@ class JbuilderTest < ActiveSupport::TestCase
|
|
192
205
|
assert_equal "world", parsed.second["content"]
|
193
206
|
end
|
194
207
|
end
|
208
|
+
|
209
|
+
test "empty top-level array" do
|
210
|
+
comments = []
|
211
|
+
|
212
|
+
json = Jbuilder.encode do |json|
|
213
|
+
json.array!(comments) do |json, comment|
|
214
|
+
json.content comment.content
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
assert_equal [], JSON.parse(json)
|
219
|
+
end
|
220
|
+
|
221
|
+
test "dynamically set a key/value" do
|
222
|
+
json = Jbuilder.encode do |json|
|
223
|
+
json.set!(:each, "stuff")
|
224
|
+
end
|
225
|
+
|
226
|
+
assert_equal "stuff", JSON.parse(json)["each"]
|
227
|
+
end
|
195
228
|
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:
|
4
|
+
version: 0.3.1
|
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:
|
12
|
+
date: 2012-01-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
16
|
-
requirement: &
|
16
|
+
requirement: &70354468053200 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 3.0.0
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70354468053200
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: blankslate
|
27
|
-
requirement: &
|
27
|
+
requirement: &70354468052720 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,13 +32,16 @@ dependencies:
|
|
32
32
|
version: 2.1.2.4
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70354468052720
|
36
36
|
description:
|
37
37
|
email: david@37signals.com
|
38
38
|
executables: []
|
39
39
|
extensions: []
|
40
40
|
extra_rdoc_files: []
|
41
41
|
files:
|
42
|
+
- ./Gemfile
|
43
|
+
- ./Gemfile.lock
|
44
|
+
- ./jbuilder-0.3.gem
|
42
45
|
- ./jbuilder.gemspec
|
43
46
|
- ./lib/jbuilder.rb
|
44
47
|
- ./lib/jbuilder_template.rb
|
@@ -65,7 +68,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
65
68
|
version: '0'
|
66
69
|
requirements: []
|
67
70
|
rubyforge_project:
|
68
|
-
rubygems_version: 1.8.
|
71
|
+
rubygems_version: 1.8.15
|
69
72
|
signing_key:
|
70
73
|
specification_version: 3
|
71
74
|
summary: Create JSON structures via a Builder-style DSL
|