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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1ac35e89f1be991b27877ffd514d8491719d0f01
4
- data.tar.gz: 317b4e79d56b2ec63b0a0248a5b26d2505581ca8
3
+ metadata.gz: c6836a60ee9c7dd9709201026f7a6b472cc2019e
4
+ data.tar.gz: 4a8069c61889a929e3ffa10b3d46b799399202a0
5
5
  SHA512:
6
- metadata.gz: 7207a0e288405e46fe0ff0469dde77087d07037f5a2a24541a046b947d1499ccff4ea3ab2e942794a4c1dd80995452531f77078c9b8a51305f819949a6d40a63
7
- data.tar.gz: 5607ad86e9171df3e826ec12f1dbc63b10fff2215cf34ea9f55ff4c50a99a5376a61648b306aa0daf7bf5040fd2db7938a63c2f35ed0d471b918b99983f307a9
6
+ metadata.gz: 774ae98b86547a5fd8261a3452e5ceb188924b9e84cf52d7c1f9c6e5f7ebfe6fb93816ef04b9f5f2aeb1f65d2136ed4d13b466957bd0cf65b3ead3a80515856f
7
+ data.tar.gz: 4aeb49c248572ceedfac7fab0bfc3d763607ead19be5dda7362d93e1bd87ddb0a1ea8b47f846747c61afb13b358c7ddc772e8d22542863ddbb948a0781fc61dd
data/.gitignore CHANGED
@@ -1,3 +1,4 @@
1
1
  tmp
2
+ gemfiles/*.lock
2
3
  Gemfile.lock
3
4
  .ruby-version
@@ -18,6 +18,7 @@ matrix:
18
18
  allow_failures:
19
19
  - rvm: jruby-19mode
20
20
  - rvm: rbx
21
+ fast_finish: true
21
22
 
22
23
  notifications:
23
24
  email: false
@@ -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
- [![Build Status](http://img.shields.io/travis/rails/jbuilder.svg)][travis]
3
+ [![Build Status](https://api.travis-ci.org/rails/jbuilder.svg)][travis]
4
4
  [![Gem Version](http://img.shields.io/gem/v/jbuilder.svg)][gem]
5
5
  [![Code Climate](http://img.shields.io/codeclimate/github/rails/jbuilder.svg)][codeclimate]
6
6
  [![Dependencies Status](http://img.shields.io/gemnasium/rails/jbuilder.svg)][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
 
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'jbuilder'
3
- s.version = '2.0.7'
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'
@@ -1,58 +1,9 @@
1
- require 'active_support/core_ext/array/access'
2
- require 'active_support/core_ext/enumerable'
3
- require 'active_support/core_ext/hash'
1
+ require 'jbuilder/jbuilder'
2
+ require 'jbuilder/key_formatter'
3
+ require 'jbuilder/errors'
4
4
  require 'multi_json'
5
5
 
6
- begin
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 { yield self }
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 { extract! value, *args }
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 { yield self }
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
- def _extract_hash_values(object, *attributes)
294
- attributes.each{ |key| _set_value key, object.fetch(key) }
295
- end
248
+ def _extract_hash_values(object, *attributes)
249
+ attributes.each{ |key| _set_value key, object.fetch(key) }
250
+ end
296
251
 
297
- def _extract_method_values(object, *attributes)
298
- attributes.each{ |key| _set_value key, object.public_send(key) }
299
- end
252
+ def _extract_method_values(object, *attributes)
253
+ attributes.each{ |key| _set_value key, object.public_send(key) }
254
+ end
300
255
 
301
- def _set_value(key, value)
302
- raise NullError, key if @attributes.nil?
303
- unless @ignore_nil && value.nil?
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
- def _map_collection(collection)
309
- return [] if collection.nil?
260
+ key = @key_formatter.format(key)
261
+ @attributes[key] = value
262
+ end
310
263
 
311
- collection.map do |element|
312
- _scope { yield element }
313
- end
314
- end
264
+ def _map_collection(collection)
265
+ return [] if collection.nil?
315
266
 
316
- def _scope
317
- parent_attributes, parent_formatter = @attributes, @key_formatter
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
- def _mapable_arguments?(value, *args)
326
- value.respond_to?(:map)
327
- end
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
 
3
3
  dependency_tracker = false
4
4
 
@@ -0,0 +1,10 @@
1
+ require 'jbuilder/jbuilder'
2
+
3
+ class Jbuilder
4
+ class NullError < ::NoMethodError
5
+ def self.build(key)
6
+ message = "Failed to add #{key.to_s.inspect} property to null object"
7
+ new(message)
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,7 @@
1
+ Jbuilder = Class.new(begin
2
+ require 'active_support/proxy_object'
3
+ ActiveSupport::ProxyObject
4
+ rescue LoadError
5
+ require 'active_support/basic_object'
6
+ ActiveSupport::BasicObject
7
+ end)
@@ -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
- def _handle_partial_options(options)
78
- options.reverse_merge! locals: {}
79
- options.reverse_merge! ::JbuilderTemplate.template_lookup_options
80
- as = options[:as]
81
-
82
- if as && options.key?(:collection)
83
- collection = options.delete(:collection) || []
84
- array!(collection) do |member|
85
- options[:locals].merge! as => member
86
- options[:locals].merge! collection: collection
87
- _render_partial options
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
- def _render_partial(options)
95
- options[:locals].merge! json: self
96
- @context.render options
97
- end
95
+ def _render_partial(options)
96
+ options[:locals].merge! json: self
97
+ @context.render options
98
+ end
98
99
 
99
- def _cache_key(key, options)
100
- if @context.respond_to?(:cache_fragment_name)
101
- # Current compatibility, fragment_name_with_digest is private again and cache_fragment_name
102
- # should be used instead.
103
- @context.cache_fragment_name(key, options)
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
- def _mapable_arguments?(value, *args)
115
- return true if super
116
- options = args.last
117
- ::Hash === options && options.key?(:as)
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
@@ -0,0 +1,7 @@
1
+ Jbuilder = Class.new(begin
2
+ require 'active_support/proxy_object'
3
+ ActiveSupport::ProxyObject)
4
+ rescue LoadError
5
+ require 'active_support/basic_object'
6
+ ActiveSupport::BasicObject)
7
+ 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(a b c)
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(1 2 3)
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(a b c), parsed
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