jbuilder 0.3 → 0.3.1
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/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
|