jbuilder 1.5.3 → 2.11.5

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.
Files changed (42) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/ruby.yml +108 -0
  3. data/.gitignore +4 -1
  4. data/Appraisals +25 -0
  5. data/CONTRIBUTING.md +106 -0
  6. data/Gemfile +4 -5
  7. data/MIT-LICENSE +2 -2
  8. data/README.md +182 -40
  9. data/Rakefile +15 -10
  10. data/gemfiles/rails_5_0.gemfile +10 -0
  11. data/gemfiles/rails_5_1.gemfile +10 -0
  12. data/gemfiles/rails_5_2.gemfile +10 -0
  13. data/gemfiles/rails_6_0.gemfile +10 -0
  14. data/gemfiles/rails_6_1.gemfile +10 -0
  15. data/gemfiles/rails_head.gemfile +10 -0
  16. data/jbuilder.gemspec +25 -8
  17. data/lib/generators/rails/jbuilder_generator.rb +13 -2
  18. data/lib/generators/rails/scaffold_controller_generator.rb +9 -3
  19. data/lib/generators/rails/templates/api_controller.rb +63 -0
  20. data/lib/generators/rails/templates/controller.rb +18 -22
  21. data/lib/generators/rails/templates/index.json.jbuilder +1 -4
  22. data/lib/generators/rails/templates/partial.json.jbuilder +16 -0
  23. data/lib/generators/rails/templates/show.json.jbuilder +1 -1
  24. data/lib/jbuilder/blank.rb +11 -0
  25. data/lib/jbuilder/collection_renderer.rb +109 -0
  26. data/lib/jbuilder/dependency_tracker.rb +61 -0
  27. data/lib/jbuilder/errors.rb +24 -0
  28. data/lib/jbuilder/jbuilder.rb +7 -0
  29. data/lib/jbuilder/jbuilder_template.rb +228 -67
  30. data/lib/jbuilder/key_formatter.rb +34 -0
  31. data/lib/jbuilder/railtie.rb +31 -6
  32. data/lib/jbuilder.rb +144 -137
  33. data/test/jbuilder_dependency_tracker_test.rb +72 -0
  34. data/test/jbuilder_generator_test.rb +31 -4
  35. data/test/jbuilder_template_test.rb +319 -163
  36. data/test/jbuilder_test.rb +613 -298
  37. data/test/scaffold_api_controller_generator_test.rb +70 -0
  38. data/test/scaffold_controller_generator_test.rb +62 -19
  39. data/test/test_helper.rb +36 -0
  40. metadata +47 -22
  41. data/.travis.yml +0 -38
  42. data/Gemfile.old +0 -7
@@ -1,254 +1,410 @@
1
- require 'test/unit'
2
- require 'mocha/setup'
3
- require 'action_view'
4
- require 'action_view/testing/resolvers'
5
- require 'active_support/cache'
6
- require 'jbuilder/jbuilder_template'
1
+ require "test_helper"
2
+ require "action_view/testing/resolvers"
3
+
4
+ class JbuilderTemplateTest < ActiveSupport::TestCase
5
+ POST_PARTIAL = <<-JBUILDER
6
+ json.extract! post, :id, :body
7
+ json.author do
8
+ first_name, last_name = post.author_name.split(nil, 2)
9
+ json.first_name first_name
10
+ json.last_name last_name
11
+ end
12
+ JBUILDER
13
+
14
+ COLLECTION_PARTIAL = <<-JBUILDER
15
+ json.extract! collection, :id, :name
16
+ JBUILDER
17
+
18
+ RACER_PARTIAL = <<-JBUILDER
19
+ json.extract! racer, :id, :name
20
+ JBUILDER
21
+
22
+ PARTIALS = {
23
+ "_partial.json.jbuilder" => "json.content content",
24
+ "_post.json.jbuilder" => POST_PARTIAL,
25
+ "racers/_racer.json.jbuilder" => RACER_PARTIAL,
26
+ "_collection.json.jbuilder" => COLLECTION_PARTIAL,
27
+
28
+ # Ensure we find only Jbuilder partials from within Jbuilder templates.
29
+ "_post.html.erb" => "Hello world!"
30
+ }
31
+
32
+ AUTHORS = [ "David Heinemeier Hansson", "Pavel Pravosud" ].cycle
33
+ POSTS = (1..10).collect { |i| Post.new(i, "Post ##{i}", AUTHORS.next) }
7
34
 
35
+ setup { Rails.cache.clear }
8
36
 
9
- BLOG_POST_PARTIAL = <<-JBUILDER
10
- json.extract! blog_post, :id, :body
11
- json.author do
12
- name = blog_post.author_name.split(nil, 2)
13
- json.first_name name[0]
14
- json.last_name name[1]
37
+ test "basic template" do
38
+ result = render('json.content "hello"')
39
+ assert_equal "hello", result["content"]
15
40
  end
16
- JBUILDER
17
41
 
18
- BlogPost = Struct.new(:id, :body, :author_name)
19
- blog_authors = [ 'David Heinemeier Hansson', 'Pavel Pravosud' ].cycle
20
- BLOG_POST_COLLECTION = 10.times.map{ |i| BlogPost.new(i+1, "post body #{i+1}", blog_authors.next) }
42
+ test "partial by name with top-level locals" do
43
+ result = render('json.partial! "partial", content: "hello"')
44
+ assert_equal "hello", result["content"]
45
+ end
21
46
 
22
- module Rails
23
- def self.cache
24
- @cache ||= ActiveSupport::Cache::MemoryStore.new
47
+ test "partial by name with nested locals" do
48
+ result = render('json.partial! "partial", locals: { content: "hello" }')
49
+ assert_equal "hello", result["content"]
25
50
  end
26
- end
27
51
 
28
- class JbuilderTemplateTest < ActionView::TestCase
29
- setup do
30
- @context = self
31
- Rails.cache.clear
52
+ test "partial by options containing nested locals" do
53
+ result = render('json.partial! partial: "partial", locals: { content: "hello" }')
54
+ assert_equal "hello", result["content"]
32
55
  end
33
56
 
34
- def partials
35
- {
36
- '_partial.json.jbuilder' => 'json.content "hello"',
37
- '_blog_post.json.jbuilder' => BLOG_POST_PARTIAL
38
- }
57
+ test "partial by options containing top-level locals" do
58
+ result = render('json.partial! partial: "partial", content: "hello"')
59
+ assert_equal "hello", result["content"]
39
60
  end
40
61
 
41
- def render_jbuilder(source)
42
- @rendered = []
43
- lookup_context.view_paths = [ActionView::FixtureResolver.new(partials.merge('test.json.jbuilder' => source))]
44
- ActionView::Template.new(source, 'test', JbuilderHandler, :virtual_path => 'test').render(self, {}).strip
62
+ test "partial for Active Model" do
63
+ result = render('json.partial! @racer', racer: Racer.new(123, "Chris Harris"))
64
+ assert_equal 123, result["id"]
65
+ assert_equal "Chris Harris", result["name"]
45
66
  end
46
67
 
47
- def undef_context_methods(*names)
48
- self.class_eval do
49
- names.each do |name|
50
- undef_method name.to_sym if self.method_defined?(name.to_sym)
51
- end
52
- end
68
+ test "partial collection by name with symbol local" do
69
+ result = render('json.partial! "post", collection: @posts, as: :post', posts: POSTS)
70
+ assert_equal 10, result.count
71
+ assert_equal "Post #5", result[4]["body"]
72
+ assert_equal "Heinemeier Hansson", result[2]["author"]["last_name"]
73
+ assert_equal "Pavel", result[5]["author"]["first_name"]
53
74
  end
54
75
 
55
- def assert_collection_rendered(json, context = nil)
56
- result = MultiJson.load(json)
57
- result = result.fetch(context) if context
76
+ test "partial collection by name with string local" do
77
+ result = render('json.partial! "post", collection: @posts, as: "post"', posts: POSTS)
78
+ assert_equal 10, result.count
79
+ assert_equal "Post #5", result[4]["body"]
80
+ assert_equal "Heinemeier Hansson", result[2]["author"]["last_name"]
81
+ assert_equal "Pavel", result[5]["author"]["first_name"]
82
+ end
58
83
 
59
- assert_equal 10, result.length
60
- assert_equal Array, result.class
61
- assert_equal 'post body 5', result[4]['body']
62
- assert_equal 'Heinemeier Hansson', result[2]['author']['last_name']
63
- assert_equal 'Pavel', result[5]['author']['first_name']
84
+ test "partial collection by options" do
85
+ result = render('json.partial! partial: "post", collection: @posts, as: :post', posts: POSTS)
86
+ assert_equal 10, result.count
87
+ assert_equal "Post #5", result[4]["body"]
88
+ assert_equal "Heinemeier Hansson", result[2]["author"]["last_name"]
89
+ assert_equal "Pavel", result[5]["author"]["first_name"]
64
90
  end
65
91
 
66
- test 'rendering' do
67
- json = render_jbuilder <<-JBUILDER
68
- json.content 'hello'
69
- JBUILDER
92
+ test "nil partial collection by name" do
93
+ assert_equal [], render('json.partial! "post", collection: @posts, as: :post', posts: nil)
94
+ end
70
95
 
71
- assert_equal 'hello', MultiJson.load(json)['content']
96
+ test "nil partial collection by options" do
97
+ assert_equal [], render('json.partial! partial: "post", collection: @posts, as: :post', posts: nil)
72
98
  end
73
99
 
74
- test 'key_format! with parameter' do
75
- json = render_jbuilder <<-JBUILDER
76
- json.key_format! :camelize => [:lower]
77
- json.camel_style 'for JS'
78
- JBUILDER
100
+ test "array of partials" do
101
+ result = render('json.array! @posts, partial: "post", as: :post', posts: POSTS)
102
+ assert_equal 10, result.count
103
+ assert_equal "Post #5", result[4]["body"]
104
+ assert_equal "Heinemeier Hansson", result[2]["author"]["last_name"]
105
+ assert_equal "Pavel", result[5]["author"]["first_name"]
106
+ end
79
107
 
80
- assert_equal ['camelStyle'], MultiJson.load(json).keys
108
+ test "empty array of partials from nil collection" do
109
+ assert_equal [], render('json.array! @posts, partial: "post", as: :post', posts: nil)
81
110
  end
82
111
 
83
- test 'key_format! propagates to child elements' do
84
- json = render_jbuilder <<-JBUILDER
85
- json.key_format! :upcase
86
- json.level1 'one'
87
- json.level2 do
88
- json.value 'two'
89
- end
90
- JBUILDER
112
+ test "array of partials under key" do
113
+ result = render('json.posts @posts, partial: "post", as: :post', posts: POSTS)
114
+ assert_equal 10, result["posts"].count
115
+ assert_equal "Post #5", result["posts"][4]["body"]
116
+ assert_equal "Heinemeier Hansson", result["posts"][2]["author"]["last_name"]
117
+ assert_equal "Pavel", result["posts"][5]["author"]["first_name"]
118
+ end
91
119
 
92
- result = MultiJson.load(json)
93
- assert_equal 'one', result['LEVEL1']
94
- assert_equal 'two', result['LEVEL2']['VALUE']
120
+ test "empty array of partials under key from nil collection" do
121
+ result = render('json.posts @posts, partial: "post", as: :post', posts: nil)
122
+ assert_equal [], result["posts"]
95
123
  end
96
124
 
97
- test 'partial! renders partial' do
98
- json = render_jbuilder <<-JBUILDER
99
- json.partial! 'partial'
125
+ test "object fragment caching" do
126
+ render(<<-JBUILDER)
127
+ json.cache! "cache-key" do
128
+ json.name "Hit"
129
+ end
100
130
  JBUILDER
101
131
 
102
- assert_equal 'hello', MultiJson.load(json)['content']
132
+ hit = render('json.cache! "cache-key" do; end')
133
+ assert_equal "Hit", hit["name"]
103
134
  end
104
135
 
105
- test 'partial! renders collections' do
106
- json = render_jbuilder <<-JBUILDER
107
- json.partial! 'blog_post', :collection => BLOG_POST_COLLECTION, :as => :blog_post
136
+ test "conditional object fragment caching" do
137
+ render(<<-JBUILDER)
138
+ json.cache_if! true, "cache-key" do
139
+ json.a "Hit"
140
+ end
141
+
142
+ json.cache_if! false, "cache-key" do
143
+ json.b "Hit"
144
+ end
108
145
  JBUILDER
109
146
 
110
- assert_collection_rendered json
111
- end
147
+ result = render(<<-JBUILDER)
148
+ json.cache_if! true, "cache-key" do
149
+ json.a "Miss"
150
+ end
112
151
 
113
- test 'partial! renders as empty array for nil-collection' do
114
- json = render_jbuilder <<-JBUILDER
115
- json.partial! 'blog_post', :collection => nil, :as => :blog_post
152
+ json.cache_if! false, "cache-key" do
153
+ json.b "Miss"
154
+ end
116
155
  JBUILDER
117
156
 
118
- assert_equal '[]', json
157
+ assert_equal "Hit", result["a"]
158
+ assert_equal "Miss", result["b"]
119
159
  end
120
160
 
121
- test 'partial! renders collection (alt. syntax)' do
122
- json = render_jbuilder <<-JBUILDER
123
- json.partial! :partial => 'blog_post', :collection => BLOG_POST_COLLECTION, :as => :blog_post
161
+ test "object fragment caching with expiry" do
162
+ travel_to Time.iso8601("2018-05-12T11:29:00-04:00")
163
+
164
+ render <<-JBUILDER
165
+ json.cache! "cache-key", expires_in: 1.minute do
166
+ json.name "Hit"
167
+ end
124
168
  JBUILDER
125
169
 
126
- assert_collection_rendered json
127
- end
170
+ travel 30.seconds
128
171
 
129
- test 'partial! renders as empty array for nil-collection (alt. syntax)' do
130
- json = render_jbuilder <<-JBUILDER
131
- json.partial! :partial => 'blog_post', :collection => nil, :as => :blog_post
172
+ result = render(<<-JBUILDER)
173
+ json.cache! "cache-key", expires_in: 1.minute do
174
+ json.name "Miss"
175
+ end
132
176
  JBUILDER
133
177
 
134
- assert_equal '[]', json
135
- end
178
+ assert_equal "Hit", result["name"]
136
179
 
137
- test 'render array of partials' do
138
- json = render_jbuilder <<-JBUILDER
139
- json.array! BLOG_POST_COLLECTION, :partial => 'blog_post', :as => :blog_post
180
+ travel 31.seconds
181
+
182
+ result = render(<<-JBUILDER)
183
+ json.cache! "cache-key", expires_in: 1.minute do
184
+ json.name "Miss"
185
+ end
140
186
  JBUILDER
141
187
 
142
- assert_collection_rendered json
188
+ assert_equal "Miss", result["name"]
143
189
  end
144
190
 
145
- test 'render array of partials as empty array with nil-collection' do
146
- json = render_jbuilder <<-JBUILDER
147
- json.array! nil, :partial => 'blog_post', :as => :blog_post
191
+ test "object root caching" do
192
+ render <<-JBUILDER
193
+ json.cache_root! "cache-key" do
194
+ json.name "Hit"
195
+ end
148
196
  JBUILDER
149
197
 
150
- assert_equal '[]', json
151
- end
198
+ assert_equal JSON.dump(name: "Hit"), Rails.cache.read("jbuilder/root/cache-key")
152
199
 
153
- test 'render array if partials as a value' do
154
- json = render_jbuilder <<-JBUILDER
155
- json.posts BLOG_POST_COLLECTION, :partial => 'blog_post', :as => :blog_post
200
+ result = render(<<-JBUILDER)
201
+ json.cache_root! "cache-key" do
202
+ json.name "Miss"
203
+ end
156
204
  JBUILDER
157
205
 
158
- assert_collection_rendered json, 'posts'
206
+ assert_equal "Hit", result["name"]
159
207
  end
160
208
 
161
- test 'render as empty array if partials as a nil value' do
162
- json = render_jbuilder <<-JBUILDER
163
- json.posts nil, :partial => 'blog_post', :as => :blog_post
209
+ test "array fragment caching" do
210
+ render <<-JBUILDER
211
+ json.cache! "cache-key" do
212
+ json.array! %w[ a b c ]
213
+ end
164
214
  JBUILDER
165
215
 
166
- assert_equal '{"posts":[]}', json
216
+ assert_equal %w[ a b c ], render('json.cache! "cache-key" do; end')
167
217
  end
168
218
 
169
- test 'fragment caching a JSON object' do
170
- undef_context_methods :fragment_name_with_digest, :cache_fragment_name
171
-
172
- render_jbuilder <<-JBUILDER
173
- json.cache! 'cachekey' do
174
- json.name 'Cache'
219
+ test "array root caching" do
220
+ render <<-JBUILDER
221
+ json.cache_root! "cache-key" do
222
+ json.array! %w[ a b c ]
175
223
  end
176
224
  JBUILDER
177
225
 
178
- json = render_jbuilder <<-JBUILDER
179
- json.cache! 'cachekey' do
180
- json.name 'Miss'
226
+ assert_equal JSON.dump(%w[ a b c ]), Rails.cache.read("jbuilder/root/cache-key")
227
+
228
+ assert_equal %w[ a b c ], render(<<-JBUILDER)
229
+ json.cache_root! "cache-key" do
230
+ json.array! %w[ d e f ]
181
231
  end
182
232
  JBUILDER
233
+ end
183
234
 
184
- parsed = MultiJson.load(json)
185
- assert_equal 'Cache', parsed['name']
235
+ test "failing to cache root after JSON structures have been defined" do
236
+ assert_raises ActionView::Template::Error, "cache_root! can't be used after JSON structures have been defined" do
237
+ render <<-JBUILDER
238
+ json.name "Kaboom"
239
+ json.cache_root! "cache-key" do
240
+ json.name "Miss"
241
+ end
242
+ JBUILDER
243
+ end
186
244
  end
187
245
 
188
- test 'fragment caching deserializes an array' do
189
- undef_context_methods :fragment_name_with_digest, :cache_fragment_name
246
+ test "empty fragment caching" do
247
+ render 'json.cache! "nothing" do; end'
190
248
 
191
- render_jbuilder <<-JBUILDER
192
- json.cache! 'cachekey' do
193
- json.array! %w(a b c)
249
+ result = nil
250
+
251
+ assert_nothing_raised do
252
+ result = render(<<-JBUILDER)
253
+ json.foo "bar"
254
+ json.cache! "nothing" do; end
255
+ JBUILDER
256
+ end
257
+
258
+ assert_equal "bar", result["foo"]
259
+ end
260
+
261
+ test "cache instrumentation" do
262
+ payloads = {}
263
+
264
+ ActiveSupport::Notifications.subscribe("read_fragment.action_controller") { |*args| payloads[:read] = args.last }
265
+ ActiveSupport::Notifications.subscribe("write_fragment.action_controller") { |*args| payloads[:write] = args.last }
266
+
267
+ render <<-JBUILDER
268
+ json.cache! "cache-key" do
269
+ json.name "Cache"
194
270
  end
195
271
  JBUILDER
196
272
 
197
- json = render_jbuilder <<-JBUILDER
198
- json.cache! 'cachekey' do
199
- json.array! %w(1 2 3)
200
- end
273
+ assert_equal "jbuilder/cache-key", payloads[:read][:key]
274
+ assert_equal "jbuilder/cache-key", payloads[:write][:key]
275
+ end
276
+
277
+ test "camelized keys" do
278
+ result = render(<<-JBUILDER)
279
+ json.key_format! camelize: [:lower]
280
+ json.first_name "David"
201
281
  JBUILDER
202
282
 
203
- parsed = MultiJson.load(json)
204
- assert_equal %w(a b c), parsed
283
+ assert_equal "David", result["firstName"]
205
284
  end
206
285
 
207
- test 'fragment caching works with previous version of cache digests' do
208
- undef_context_methods :cache_fragment_name
286
+ if JbuilderTemplate::CollectionRenderer.supported?
287
+ test "returns an empty array for an empty collection" do
288
+ result = render('json.array! @posts, partial: "post", as: :post, cached: true', posts: [])
209
289
 
210
- @context.expects :fragment_name_with_digest
290
+ # Do not use #assert_empty as it is important to ensure that the type of the JSON result is an array.
291
+ assert_equal [], result
292
+ end
211
293
 
212
- render_jbuilder <<-JBUILDER
213
- json.cache! 'cachekey' do
214
- json.name 'Cache'
294
+ test "works with an enumerable object" do
295
+ enumerable_class = Class.new do
296
+ include Enumerable
297
+ alias length count # Rails 6.1 requires this.
298
+
299
+ def each(&block)
300
+ [].each(&block)
301
+ end
215
302
  end
216
- JBUILDER
217
- end
218
303
 
219
- test 'fragment caching works with current cache digests' do
220
- undef_context_methods :fragment_name_with_digest
304
+ result = render('json.array! @posts, partial: "post", as: :post, cached: true', posts: enumerable_class.new)
305
+
306
+ # Do not use #assert_empty as it is important to ensure that the type of the JSON result is an array.
307
+ assert_equal [], result
308
+ end
309
+
310
+ test "supports the cached: true option" do
311
+ result = render('json.array! @posts, partial: "post", as: :post, cached: true', posts: POSTS)
312
+
313
+ assert_equal 10, result.count
314
+ assert_equal "Post #5", result[4]["body"]
315
+ assert_equal "Heinemeier Hansson", result[2]["author"]["last_name"]
316
+ assert_equal "Pavel", result[5]["author"]["first_name"]
317
+
318
+ expected = {
319
+ "id" => 1,
320
+ "body" => "Post #1",
321
+ "author" => {
322
+ "first_name" => "David",
323
+ "last_name" => "Heinemeier Hansson"
324
+ }
325
+ }
326
+
327
+ assert_equal expected, Rails.cache.read("post-1")
328
+
329
+ result = render('json.array! @posts, partial: "post", as: :post, cached: true', posts: POSTS)
330
+
331
+ assert_equal 10, result.count
332
+ assert_equal "Post #5", result[4]["body"]
333
+ assert_equal "Heinemeier Hansson", result[2]["author"]["last_name"]
334
+ assert_equal "Pavel", result[5]["author"]["first_name"]
335
+ end
221
336
 
222
- @context.expects :cache_fragment_name
337
+ test "supports the cached: ->() {} option" do
338
+ result = render('json.array! @posts, partial: "post", as: :post, cached: ->(post) { [post, "foo"] }', posts: POSTS)
223
339
 
224
- render_jbuilder <<-JBUILDER
225
- json.cache! 'cachekey' do
226
- json.name 'Cache'
340
+ assert_equal 10, result.count
341
+ assert_equal "Post #5", result[4]["body"]
342
+ assert_equal "Heinemeier Hansson", result[2]["author"]["last_name"]
343
+ assert_equal "Pavel", result[5]["author"]["first_name"]
344
+
345
+ expected = {
346
+ "id" => 1,
347
+ "body" => "Post #1",
348
+ "author" => {
349
+ "first_name" => "David",
350
+ "last_name" => "Heinemeier Hansson"
351
+ }
352
+ }
353
+
354
+ assert_equal expected, Rails.cache.read("post-1/foo")
355
+
356
+ result = render('json.array! @posts, partial: "post", as: :post, cached: ->(post) { [post, "foo"] }', posts: POSTS)
357
+
358
+ assert_equal 10, result.count
359
+ assert_equal "Post #5", result[4]["body"]
360
+ assert_equal "Heinemeier Hansson", result[2]["author"]["last_name"]
361
+ assert_equal "Pavel", result[5]["author"]["first_name"]
362
+ end
363
+
364
+ test "raises an error on a render call with the :layout option" do
365
+ error = assert_raises NotImplementedError do
366
+ render('json.array! @posts, partial: "post", as: :post, layout: "layout"', posts: POSTS)
227
367
  end
228
- JBUILDER
229
- end
230
368
 
231
- test 'does not perform caching when controller.perform_caching is false' do
232
- controller.perform_caching = false
233
- render_jbuilder <<-JBUILDER
234
- json.cache! 'cachekey' do
235
- json.name 'Cache'
369
+ assert_equal "The `:layout' option is not supported in collection rendering.", error.message
370
+ end
371
+
372
+ test "raises an error on a render call with the :spacer_template option" do
373
+ error = assert_raises NotImplementedError do
374
+ render('json.array! @posts, partial: "post", as: :post, spacer_template: "template"', posts: POSTS)
236
375
  end
237
- JBUILDER
238
376
 
239
- assert_equal Rails.cache.inspect[/entries=(\d+)/, 1], '0'
377
+ assert_equal "The `:spacer_template' option is not supported in collection rendering.", error.message
378
+ end
240
379
  end
241
380
 
242
- test 'fragment caching falls back on ActiveSupport::Cache.expand_cache_key' do
243
- undef_context_methods :fragment_name_with_digest, :cache_fragment_name
381
+ private
382
+ def render(*args)
383
+ JSON.load render_without_parsing(*args)
384
+ end
385
+
386
+ def render_without_parsing(source, assigns = {})
387
+ view = build_view(fixtures: PARTIALS.merge("source.json.jbuilder" => source), assigns: assigns)
388
+ view.render(template: "source")
389
+ end
244
390
 
245
- ActiveSupport::Cache.expects :expand_cache_key
391
+ def build_view(options = {})
392
+ resolver = ActionView::FixtureResolver.new(options.fetch(:fixtures))
393
+ lookup_context = ActionView::LookupContext.new([ resolver ], {}, [""])
394
+ controller = ActionView::TestCase::TestController.new
246
395
 
247
- render_jbuilder <<-JBUILDER
248
- json.cache! 'cachekey' do
249
- json.name 'Cache'
396
+ # TODO: Use with_empty_template_cache unconditionally after dropping support for Rails <6.0.
397
+ view = if ActionView::Base.respond_to?(:with_empty_template_cache)
398
+ ActionView::Base.with_empty_template_cache.new(lookup_context, options.fetch(:assigns, {}), controller)
399
+ else
400
+ ActionView::Base.new(lookup_context, options.fetch(:assigns, {}), controller)
250
401
  end
251
- JBUILDER
252
- end
253
402
 
254
- end
403
+ def view.view_cache_dependencies; []; end
404
+ def view.combined_fragment_cache_key(key) [ key ] end
405
+ def view.cache_fragment_name(key, *) key end
406
+ def view.fragment_name_with_digest(key) key end
407
+
408
+ view
409
+ end
410
+ end