jbuilder 2.0.7 → 2.0.8
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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +1 -0
- data/CHANGELOG.md +8 -0
- data/README.md +5 -1
- data/jbuilder.gemspec +1 -1
- data/lib/jbuilder.rb +42 -86
- data/lib/jbuilder/dependency_tracker.rb +1 -1
- data/lib/jbuilder/errors.rb +10 -0
- data/lib/jbuilder/jbuilder.rb +7 -0
- data/lib/jbuilder/jbuilder_template.rb +41 -34
- data/lib/jbuilder/key_formatter.rb +34 -0
- data/lib/jbuilder/proxy.rb +7 -0
- data/test/jbuilder_template_test.rb +5 -15
- data/test/jbuilder_test.rb +204 -209
- metadata +6 -7
- data/gemfiles/rails_3_0.gemfile.lock +0 -66
- data/gemfiles/rails_3_1.gemfile.lock +0 -76
- data/gemfiles/rails_3_2.gemfile.lock +0 -75
- data/gemfiles/rails_4_0.gemfile.lock +0 -57
- data/gemfiles/rails_4_1.gemfile.lock +0 -62
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c6836a60ee9c7dd9709201026f7a6b472cc2019e
|
4
|
+
data.tar.gz: 4a8069c61889a929e3ffa10b3d46b799399202a0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 774ae98b86547a5fd8261a3452e5ceb188924b9e84cf52d7c1f9c6e5f7ebfe6fb93816ef04b9f5f2aeb1f65d2136ed4d13b466957bd0cf65b3ead3a80515856f
|
7
|
+
data.tar.gz: 4aeb49c248572ceedfac7fab0bfc3d763607ead19be5dda7362d93e1bd87ddb0a1ea8b47f846747c61afb13b358c7ddc772e8d22542863ddbb948a0781fc61dd
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
2.0.8
|
4
|
+
-----
|
5
|
+
* [Eliminate circular dependencies](https://github.com/rails/jbuilder/commit/0879484dc74e7be93b695f66e3708ba48cdb1be3)
|
6
|
+
* [Support cache key generation for complex objects](https://github.com/rails/jbuilder/commit/ca9622cca30c1112dd4408fcb2e658849abe1dd5)
|
7
|
+
* [Remove JbuilderProxy class](https://github.com/rails/jbuilder/commit/5877482fc7da3224e42d4f72a1386f7a3a08173b)
|
8
|
+
* [Move KeyFormatter into a separate file](https://github.com/rails/jbuilder/commit/13fee8464ff53ce853030114283c03c135c052b6)
|
9
|
+
* [Move NullError into a separate file](https://github.com/rails/jbuilder/commit/13fee8464ff53ce853030114283c03c135c052b6)
|
10
|
+
|
3
11
|
2.0.7
|
4
12
|
-----
|
5
13
|
* [Add destroy notice to scaffold generator](https://github.com/rails/jbuilder/commit/8448e86f8cdfa0f517bd59576947875775a1d43c)
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Jbuilder
|
2
2
|
|
3
|
-
[][travis]
|
4
4
|
[][gem]
|
5
5
|
[][codeclimate]
|
6
6
|
[][gemnasium]
|
@@ -205,6 +205,10 @@ json.cache_if! !admin?, ['v1', @person], expires_in: 10.minutes do
|
|
205
205
|
end
|
206
206
|
```
|
207
207
|
|
208
|
+
If you are rendering fragments for a collection of objects, have a look at
|
209
|
+
`jbuilder_cache_multi` gem. It uses fetch_multi (>= Rails 4.1) to fetch
|
210
|
+
multiple keys at once.
|
211
|
+
|
208
212
|
Keys can be auto formatted using `key_format!`, this can be used to convert
|
209
213
|
keynames from the standard ruby_format to camelCase:
|
210
214
|
|
data/jbuilder.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'jbuilder'
|
3
|
-
s.version = '2.0.
|
3
|
+
s.version = '2.0.8'
|
4
4
|
s.authors = ['David Heinemeier Hansson', 'Pavel Pravosud']
|
5
5
|
s.email = ['david@37signals.com', 'pavel@pravosud.com']
|
6
6
|
s.summary = 'Create JSON structures via a Builder-style DSL'
|
data/lib/jbuilder.rb
CHANGED
@@ -1,58 +1,9 @@
|
|
1
|
-
require '
|
2
|
-
require '
|
3
|
-
require '
|
1
|
+
require 'jbuilder/jbuilder'
|
2
|
+
require 'jbuilder/key_formatter'
|
3
|
+
require 'jbuilder/errors'
|
4
4
|
require 'multi_json'
|
5
5
|
|
6
|
-
|
7
|
-
require 'active_support/proxy_object'
|
8
|
-
JbuilderProxy = ActiveSupport::ProxyObject
|
9
|
-
rescue LoadError
|
10
|
-
require 'active_support/basic_object'
|
11
|
-
JbuilderProxy = ActiveSupport::BasicObject
|
12
|
-
end
|
13
|
-
|
14
|
-
class Jbuilder < JbuilderProxy
|
15
|
-
class NullError < ::NoMethodError
|
16
|
-
def initialize(key)
|
17
|
-
super "Failed to add #{key.to_s.inspect} property to null object"
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
class KeyFormatter
|
22
|
-
def initialize(*args)
|
23
|
-
@format = {}
|
24
|
-
@cache = {}
|
25
|
-
|
26
|
-
options = args.extract_options!
|
27
|
-
args.each do |name|
|
28
|
-
@format[name] = []
|
29
|
-
end
|
30
|
-
options.each do |name, paramaters|
|
31
|
-
@format[name] = paramaters
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def initialize_copy(original)
|
36
|
-
@cache = {}
|
37
|
-
end
|
38
|
-
|
39
|
-
def format(key)
|
40
|
-
@cache[key] ||= @format.inject(key.to_s) do |result, args|
|
41
|
-
func, args = args
|
42
|
-
if ::Proc === func
|
43
|
-
func.call result, *args
|
44
|
-
else
|
45
|
-
result.send func, *args
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
# Yields a builder and automatically turns the result into a JSON string
|
52
|
-
def self.encode(*args, &block)
|
53
|
-
new(*args, &block).target!
|
54
|
-
end
|
55
|
-
|
6
|
+
class Jbuilder
|
56
7
|
@@key_formatter = KeyFormatter.new
|
57
8
|
@@ignore_nil = false
|
58
9
|
|
@@ -61,13 +12,18 @@ class Jbuilder < JbuilderProxy
|
|
61
12
|
|
62
13
|
@key_formatter = options.fetch(:key_formatter){ @@key_formatter.clone }
|
63
14
|
@ignore_nil = options.fetch(:ignore_nil, @@ignore_nil)
|
15
|
+
|
64
16
|
yield self if block
|
65
17
|
end
|
66
18
|
|
19
|
+
# Yields a builder and automatically turns the result into a JSON string
|
20
|
+
def self.encode(*args, &block)
|
21
|
+
new(*args, &block).target!
|
22
|
+
end
|
23
|
+
|
67
24
|
BLANK = ::Object.new
|
68
25
|
|
69
26
|
def set!(key, value = BLANK, *args, &block)
|
70
|
-
|
71
27
|
result = if block
|
72
28
|
if BLANK != value
|
73
29
|
# json.comments @post.comments { |comment| ... }
|
@@ -76,7 +32,7 @@ class Jbuilder < JbuilderProxy
|
|
76
32
|
else
|
77
33
|
# json.comments { ... }
|
78
34
|
# { "comments": ... }
|
79
|
-
_scope
|
35
|
+
_scope{ yield self }
|
80
36
|
end
|
81
37
|
elsif args.empty?
|
82
38
|
if ::Jbuilder === value
|
@@ -96,7 +52,7 @@ class Jbuilder < JbuilderProxy
|
|
96
52
|
else
|
97
53
|
# json.author @post.creator, :name, :email_address
|
98
54
|
# { "author": { "name": "David", "email_address": "david@loudthinking.com" } }
|
99
|
-
_scope
|
55
|
+
_scope{ extract! value, *args }
|
100
56
|
end
|
101
57
|
|
102
58
|
_set_value key, result
|
@@ -105,7 +61,6 @@ class Jbuilder < JbuilderProxy
|
|
105
61
|
alias_method :method_missing, :set!
|
106
62
|
private :method_missing
|
107
63
|
|
108
|
-
|
109
64
|
# Specifies formatting to be applied to the key. Passing in a name of a function
|
110
65
|
# will cause that function to be called on the key. So :upcase will upper case
|
111
66
|
# the key. You can also pass in lambdas for more complex transformations.
|
@@ -185,7 +140,7 @@ class Jbuilder < JbuilderProxy
|
|
185
140
|
# end
|
186
141
|
def child!
|
187
142
|
@attributes = [] unless ::Array === @attributes
|
188
|
-
@attributes << _scope
|
143
|
+
@attributes << _scope{ yield self }
|
189
144
|
end
|
190
145
|
|
191
146
|
# Turns the current element into an array and iterates over the passed collection, adding each iteration as
|
@@ -290,41 +245,42 @@ class Jbuilder < JbuilderProxy
|
|
290
245
|
|
291
246
|
private
|
292
247
|
|
293
|
-
|
294
|
-
|
295
|
-
|
248
|
+
def _extract_hash_values(object, *attributes)
|
249
|
+
attributes.each{ |key| _set_value key, object.fetch(key) }
|
250
|
+
end
|
296
251
|
|
297
|
-
|
298
|
-
|
299
|
-
|
252
|
+
def _extract_method_values(object, *attributes)
|
253
|
+
attributes.each{ |key| _set_value key, object.public_send(key) }
|
254
|
+
end
|
300
255
|
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
@attributes[@key_formatter.format(key)] = value
|
305
|
-
end
|
306
|
-
end
|
256
|
+
def _set_value(key, value)
|
257
|
+
raise NullError.build(key) if @attributes.nil?
|
258
|
+
return if @ignore_nil && value.nil?
|
307
259
|
|
308
|
-
|
309
|
-
|
260
|
+
key = @key_formatter.format(key)
|
261
|
+
@attributes[key] = value
|
262
|
+
end
|
310
263
|
|
311
|
-
|
312
|
-
|
313
|
-
end
|
314
|
-
end
|
264
|
+
def _map_collection(collection)
|
265
|
+
return [] if collection.nil?
|
315
266
|
|
316
|
-
|
317
|
-
|
318
|
-
@attributes = {}
|
319
|
-
yield
|
320
|
-
@attributes
|
321
|
-
ensure
|
322
|
-
@attributes, @key_formatter = parent_attributes, parent_formatter
|
267
|
+
collection.map do |element|
|
268
|
+
_scope{ yield element }
|
323
269
|
end
|
270
|
+
end
|
324
271
|
|
325
|
-
|
326
|
-
|
327
|
-
|
272
|
+
def _scope
|
273
|
+
parent_attributes, parent_formatter = @attributes, @key_formatter
|
274
|
+
@attributes = {}
|
275
|
+
yield
|
276
|
+
@attributes
|
277
|
+
ensure
|
278
|
+
@attributes, @key_formatter = parent_attributes, parent_formatter
|
279
|
+
end
|
280
|
+
|
281
|
+
def _mapable_arguments?(value, *args)
|
282
|
+
value.respond_to?(:map)
|
283
|
+
end
|
328
284
|
end
|
329
285
|
|
330
286
|
require 'jbuilder/jbuilder_template' if defined?(ActionView::Template)
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'jbuilder'
|
1
|
+
require 'jbuilder/jbuilder'
|
2
2
|
require 'action_dispatch/http/mime_type'
|
3
3
|
require 'active_support/cache'
|
4
4
|
|
@@ -74,48 +74,55 @@ class JbuilderTemplate < Jbuilder
|
|
74
74
|
end
|
75
75
|
|
76
76
|
protected
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
end
|
89
|
-
else
|
77
|
+
|
78
|
+
def _handle_partial_options(options)
|
79
|
+
options.reverse_merge! locals: {}
|
80
|
+
options.reverse_merge! ::JbuilderTemplate.template_lookup_options
|
81
|
+
as = options[:as]
|
82
|
+
|
83
|
+
if as && options.key?(:collection)
|
84
|
+
collection = options.delete(:collection) || []
|
85
|
+
array!(collection) do |member|
|
86
|
+
options[:locals].merge! as => member
|
87
|
+
options[:locals].merge! collection: collection
|
90
88
|
_render_partial options
|
91
89
|
end
|
90
|
+
else
|
91
|
+
_render_partial options
|
92
92
|
end
|
93
|
+
end
|
93
94
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
95
|
+
def _render_partial(options)
|
96
|
+
options[:locals].merge! json: self
|
97
|
+
@context.render options
|
98
|
+
end
|
98
99
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
elsif @context.respond_to?(:fragment_name_with_digest)
|
105
|
-
# Backwards compatibility for period of time when fragment_name_with_digest was made public.
|
106
|
-
@context.fragment_name_with_digest(key)
|
107
|
-
else
|
108
|
-
::ActiveSupport::Cache.expand_cache_key(key.is_a?(::Hash) ? url_for(key).split('://').last : key, :jbuilder)
|
109
|
-
end
|
110
|
-
end
|
100
|
+
def _cache_key(key, options)
|
101
|
+
key = _fragment_name_with_digest(key, options)
|
102
|
+
key = url_for(key).split('://', 2).last if ::Hash === key
|
103
|
+
::ActiveSupport::Cache.expand_cache_key(key, :jbuilder)
|
104
|
+
end
|
111
105
|
|
112
106
|
private
|
113
107
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
108
|
+
def _fragment_name_with_digest(key, options)
|
109
|
+
if @context.respond_to?(:cache_fragment_name)
|
110
|
+
# Current compatibility, fragment_name_with_digest is private again and cache_fragment_name
|
111
|
+
# should be used instead.
|
112
|
+
@context.cache_fragment_name(key, options)
|
113
|
+
elsif @context.respond_to?(:fragment_name_with_digest)
|
114
|
+
# Backwards compatibility for period of time when fragment_name_with_digest was made public.
|
115
|
+
@context.fragment_name_with_digest(key)
|
116
|
+
else
|
117
|
+
key
|
118
118
|
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def _mapable_arguments?(value, *args)
|
122
|
+
return true if super
|
123
|
+
options = args.last
|
124
|
+
::Hash === options && options.key?(:as)
|
125
|
+
end
|
119
126
|
end
|
120
127
|
|
121
128
|
class JbuilderHandler
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'jbuilder/jbuilder'
|
2
|
+
require 'active_support/core_ext/array'
|
3
|
+
|
4
|
+
class Jbuilder
|
5
|
+
class KeyFormatter
|
6
|
+
def initialize(*args)
|
7
|
+
@format = {}
|
8
|
+
@cache = {}
|
9
|
+
|
10
|
+
options = args.extract_options!
|
11
|
+
args.each do |name|
|
12
|
+
@format[name] = []
|
13
|
+
end
|
14
|
+
options.each do |name, paramaters|
|
15
|
+
@format[name] = paramaters
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize_copy(original)
|
20
|
+
@cache = {}
|
21
|
+
end
|
22
|
+
|
23
|
+
def format(key)
|
24
|
+
@cache[key] ||= @format.inject(key.to_s) do |result, args|
|
25
|
+
func, args = args
|
26
|
+
if ::Proc === func
|
27
|
+
func.call result, *args
|
28
|
+
else
|
29
|
+
result.send func, *args
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -216,18 +216,18 @@ class JbuilderTemplateTest < ActionView::TestCase
|
|
216
216
|
|
217
217
|
render_jbuilder <<-JBUILDER
|
218
218
|
json.cache! 'cachekey' do
|
219
|
-
json.array! %w
|
219
|
+
json.array! %w[a b c]
|
220
220
|
end
|
221
221
|
JBUILDER
|
222
222
|
|
223
223
|
json = render_jbuilder <<-JBUILDER
|
224
224
|
json.cache! 'cachekey' do
|
225
|
-
json.array! %w
|
225
|
+
json.array! %w[1 2 3]
|
226
226
|
end
|
227
227
|
JBUILDER
|
228
228
|
|
229
229
|
parsed = MultiJson.load(json)
|
230
|
-
assert_equal %w
|
230
|
+
assert_equal %w[a b c], parsed
|
231
231
|
end
|
232
232
|
|
233
233
|
test 'fragment caching works with previous version of cache digests' do
|
@@ -246,6 +246,7 @@ class JbuilderTemplateTest < ActionView::TestCase
|
|
246
246
|
undef_context_methods :fragment_name_with_digest
|
247
247
|
|
248
248
|
@context.expects :cache_fragment_name
|
249
|
+
ActiveSupport::Cache.expects :expand_cache_key
|
249
250
|
|
250
251
|
render_jbuilder <<-JBUILDER
|
251
252
|
json.cache! 'cachekey' do
|
@@ -258,6 +259,7 @@ class JbuilderTemplateTest < ActionView::TestCase
|
|
258
259
|
undef_context_methods :fragment_name_with_digest
|
259
260
|
|
260
261
|
@context.expects(:cache_fragment_name).with('cachekey', skip_digest: true)
|
262
|
+
ActiveSupport::Cache.expects :expand_cache_key
|
261
263
|
|
262
264
|
render_jbuilder <<-JBUILDER
|
263
265
|
json.cache! 'cachekey', skip_digest: true do
|
@@ -277,16 +279,4 @@ class JbuilderTemplateTest < ActionView::TestCase
|
|
277
279
|
assert_equal Rails.cache.inspect[/entries=(\d+)/, 1], '0'
|
278
280
|
end
|
279
281
|
|
280
|
-
test 'fragment caching falls back on ActiveSupport::Cache.expand_cache_key' do
|
281
|
-
undef_context_methods :fragment_name_with_digest, :cache_fragment_name
|
282
|
-
|
283
|
-
ActiveSupport::Cache.expects :expand_cache_key
|
284
|
-
|
285
|
-
render_jbuilder <<-JBUILDER
|
286
|
-
json.cache! 'cachekey' do
|
287
|
-
json.name 'Cache'
|
288
|
-
end
|
289
|
-
JBUILDER
|
290
|
-
end
|
291
|
-
|
292
282
|
end
|