jbuilder 2.0.7 → 2.0.8

Sign up to get free protection for your applications and to get access to all the features.
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