jbuilder 2.11.0 → 2.14.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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/.devcontainer/devcontainer.json +25 -0
  3. data/.github/workflows/ruby.yml +56 -0
  4. data/.gitignore +1 -0
  5. data/Appraisals +14 -13
  6. data/CONTRIBUTING.md +4 -10
  7. data/Gemfile +2 -0
  8. data/README.md +113 -26
  9. data/Rakefile +3 -1
  10. data/bin/release +14 -0
  11. data/bin/test +6 -0
  12. data/gemfiles/{rails_5_1.gemfile → rails_7_0.gemfile} +2 -1
  13. data/gemfiles/{rails_5_2.gemfile → rails_7_1.gemfile} +1 -1
  14. data/gemfiles/{rails_6_0.gemfile → rails_7_2.gemfile} +1 -1
  15. data/gemfiles/{rails_5_0.gemfile → rails_8_0.gemfile} +1 -1
  16. data/gemfiles/rails_head.gemfile +1 -1
  17. data/jbuilder.gemspec +16 -3
  18. data/lib/generators/rails/jbuilder_generator.rb +6 -0
  19. data/lib/generators/rails/scaffold_controller_generator.rb +2 -0
  20. data/lib/generators/rails/templates/api_controller.rb +7 -1
  21. data/lib/generators/rails/templates/controller.rb +16 -14
  22. data/lib/generators/rails/templates/index.json.jbuilder +1 -1
  23. data/lib/generators/rails/templates/show.json.jbuilder +1 -1
  24. data/lib/jbuilder/blank.rb +2 -0
  25. data/lib/jbuilder/collection_renderer.rb +58 -0
  26. data/lib/jbuilder/errors.rb +3 -1
  27. data/lib/jbuilder/jbuilder.rb +3 -7
  28. data/lib/jbuilder/jbuilder_dependency_tracker.rb +75 -0
  29. data/lib/jbuilder/jbuilder_template.rb +81 -47
  30. data/lib/jbuilder/key_formatter.rb +19 -21
  31. data/lib/jbuilder/railtie.rb +17 -19
  32. data/lib/jbuilder/version.rb +5 -0
  33. data/lib/jbuilder.rb +84 -50
  34. data/test/jbuilder_dependency_tracker_test.rb +2 -3
  35. data/test/jbuilder_generator_test.rb +19 -9
  36. data/test/jbuilder_template_test.rb +133 -8
  37. data/test/jbuilder_test.rb +152 -14
  38. data/test/scaffold_api_controller_generator_test.rb +52 -47
  39. data/test/scaffold_controller_generator_test.rb +38 -12
  40. data/test/test_helper.rb +23 -10
  41. metadata +37 -18
  42. data/.travis.yml +0 -52
  43. data/CHANGELOG.md +0 -300
  44. data/lib/jbuilder/dependency_tracker.rb +0 -61
data/lib/jbuilder.rb CHANGED
@@ -1,31 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support'
1
4
  require 'jbuilder/jbuilder'
2
5
  require 'jbuilder/blank'
3
6
  require 'jbuilder/key_formatter'
4
7
  require 'jbuilder/errors'
5
8
  require 'json'
6
- require 'ostruct'
7
9
  require 'active_support/core_ext/hash/deep_merge'
8
10
 
9
11
  class Jbuilder
10
12
  @@key_formatter = nil
11
13
  @@ignore_nil = false
12
-
13
- def initialize(options = {})
14
+ @@deep_format_keys = false
15
+
16
+ def initialize(
17
+ key_formatter: @@key_formatter,
18
+ ignore_nil: @@ignore_nil,
19
+ deep_format_keys: @@deep_format_keys,
20
+ &block
21
+ )
14
22
  @attributes = {}
23
+ @key_formatter = key_formatter
24
+ @ignore_nil = ignore_nil
25
+ @deep_format_keys = deep_format_keys
15
26
 
16
- @key_formatter = options.fetch(:key_formatter){ @@key_formatter ? @@key_formatter.clone : nil}
17
- @ignore_nil = options.fetch(:ignore_nil, @@ignore_nil)
18
-
19
- yield self if ::Kernel.block_given?
27
+ yield self if block
20
28
  end
21
29
 
22
30
  # Yields a builder and automatically turns the result into a JSON string
23
- def self.encode(*args, &block)
24
- new(*args, &block).target!
31
+ def self.encode(...)
32
+ new(...).target!
25
33
  end
26
34
 
27
35
  BLANK = Blank.new
28
- NON_ENUMERABLES = [ ::Struct, ::OpenStruct ].to_set
29
36
 
30
37
  def set!(key, value = BLANK, *args, &block)
31
38
  result = if ::Kernel.block_given?
@@ -56,20 +63,12 @@ class Jbuilder
56
63
  else
57
64
  # json.author @post.creator, :name, :email_address
58
65
  # { "author": { "name": "David", "email_address": "david@loudthinking.com" } }
59
- _merge_block(key){ extract! value, *args }
66
+ _merge_block(key){ _extract value, args }
60
67
  end
61
68
 
62
69
  _set_value key, result
63
70
  end
64
71
 
65
- def method_missing(*args, &block)
66
- if ::Kernel.block_given?
67
- set!(*args, &block)
68
- else
69
- set!(*args)
70
- end
71
- end
72
-
73
72
  # Specifies formatting to be applied to the key. Passing in a name of a function
74
73
  # will cause that function to be called on the key. So :upcase will upper case
75
74
  # the key. You can also pass in lambdas for more complex transformations.
@@ -98,13 +97,13 @@ class Jbuilder
98
97
  #
99
98
  # { "_first_name": "David" }
100
99
  #
101
- def key_format!(*args)
102
- @key_formatter = KeyFormatter.new(*args)
100
+ def key_format!(...)
101
+ @key_formatter = KeyFormatter.new(...)
103
102
  end
104
103
 
105
104
  # Same as the instance method key_format! except sets the default.
106
- def self.key_format(*args)
107
- @@key_formatter = KeyFormatter.new(*args)
105
+ def self.key_format(...)
106
+ @@key_formatter = KeyFormatter.new(...)
108
107
  end
109
108
 
110
109
  # If you want to skip adding nil values to your JSON hash. This is useful
@@ -131,6 +130,31 @@ class Jbuilder
131
130
  @@ignore_nil = value
132
131
  end
133
132
 
133
+ # Deeply apply key format to nested hashes and arrays passed to
134
+ # methods like set!, merge! or array!.
135
+ #
136
+ # Example:
137
+ #
138
+ # json.key_format! camelize: :lower
139
+ # json.settings({some_value: "abc"})
140
+ #
141
+ # { "settings": { "some_value": "abc" }}
142
+ #
143
+ # json.key_format! camelize: :lower
144
+ # json.deep_format_keys!
145
+ # json.settings({some_value: "abc"})
146
+ #
147
+ # { "settings": { "someValue": "abc" }}
148
+ #
149
+ def deep_format_keys!(value = true)
150
+ @deep_format_keys = value
151
+ end
152
+
153
+ # Same as instance method deep_format_keys! except sets the default.
154
+ def self.deep_format_keys(value = true)
155
+ @@deep_format_keys = value
156
+ end
157
+
134
158
  # Turns the current element into an array and yields a builder to add a hash.
135
159
  #
136
160
  # Example:
@@ -188,12 +212,12 @@ class Jbuilder
188
212
  elsif ::Kernel.block_given?
189
213
  _map_collection(collection, &block)
190
214
  elsif attributes.any?
191
- _map_collection(collection) { |element| extract! element, *attributes }
215
+ _map_collection(collection) { |element| _extract element, attributes }
192
216
  else
193
- collection.to_a
217
+ _format_keys(collection.to_a)
194
218
  end
195
219
 
196
- merge! array
220
+ @attributes = _merge_values(@attributes, array)
197
221
  end
198
222
 
199
223
  # Extracts the mentioned attributes or hash elements from the passed object and turns them into attributes of the JSON.
@@ -214,18 +238,14 @@ class Jbuilder
214
238
  #
215
239
  # json.(@person, :name, :age)
216
240
  def extract!(object, *attributes)
217
- if ::Hash === object
218
- _extract_hash_values(object, attributes)
219
- else
220
- _extract_method_values(object, attributes)
221
- end
241
+ _extract object, attributes
222
242
  end
223
243
 
224
244
  def call(object, *attributes, &block)
225
245
  if ::Kernel.block_given?
226
246
  array! object, &block
227
247
  else
228
- extract! object, *attributes
248
+ _extract object, attributes
229
249
  end
230
250
  end
231
251
 
@@ -244,7 +264,7 @@ class Jbuilder
244
264
  # Merges hash, array, or Jbuilder instance into current builder.
245
265
  def merge!(object)
246
266
  hash_or_array = ::Jbuilder === object ? object.attributes! : object
247
- @attributes = _merge_values(@attributes, hash_or_array)
267
+ @attributes = _merge_values(@attributes, _format_keys(hash_or_array))
248
268
  end
249
269
 
250
270
  # Encodes the current builder as JSON.
@@ -254,17 +274,27 @@ class Jbuilder
254
274
 
255
275
  private
256
276
 
277
+ alias_method :method_missing, :set!
278
+
279
+ def _extract(object, attributes)
280
+ if ::Hash === object
281
+ _extract_hash_values(object, attributes)
282
+ else
283
+ _extract_method_values(object, attributes)
284
+ end
285
+ end
286
+
257
287
  def _extract_hash_values(object, attributes)
258
- attributes.each{ |key| _set_value key, object.fetch(key) }
288
+ attributes.each{ |key| _set_value key, _format_keys(object.fetch(key)) }
259
289
  end
260
290
 
261
291
  def _extract_method_values(object, attributes)
262
- attributes.each{ |key| _set_value key, object.public_send(key) }
292
+ attributes.each{ |key| _set_value key, _format_keys(object.public_send(key)) }
263
293
  end
264
294
 
265
295
  def _merge_block(key)
266
296
  current_value = _blank? ? BLANK : @attributes.fetch(_key(key), BLANK)
267
- raise NullError.build(key) if current_value.nil?
297
+ ::Kernel.raise NullError.build(key) if current_value.nil?
268
298
  new_value = _scope{ yield self }
269
299
  _merge_values(current_value, new_value)
270
300
  end
@@ -273,21 +303,29 @@ class Jbuilder
273
303
  if _blank?(updates)
274
304
  current_value
275
305
  elsif _blank?(current_value) || updates.nil? || current_value.empty? && ::Array === updates
276
- _format_keys(updates)
306
+ updates
277
307
  elsif ::Array === current_value && ::Array === updates
278
- current_value + _format_keys(updates)
308
+ current_value + updates
279
309
  elsif ::Hash === current_value && ::Hash === updates
280
- current_value.deep_merge(_format_keys(updates))
310
+ current_value.deep_merge(updates)
281
311
  else
282
- raise MergeError.build(current_value, updates)
312
+ ::Kernel.raise MergeError.build(current_value, updates)
283
313
  end
284
314
  end
285
315
 
286
316
  def _key(key)
287
- @key_formatter ? @key_formatter.format(key) : key.to_s
317
+ if @key_formatter
318
+ @key_formatter.format(key)
319
+ elsif key.is_a?(::Symbol)
320
+ key.name
321
+ else
322
+ key.to_s
323
+ end
288
324
  end
289
325
 
290
326
  def _format_keys(hash_or_array)
327
+ return hash_or_array unless @deep_format_keys
328
+
291
329
  if ::Array === hash_or_array
292
330
  hash_or_array.map { |value| _format_keys(value) }
293
331
  elsif ::Hash === hash_or_array
@@ -298,8 +336,8 @@ class Jbuilder
298
336
  end
299
337
 
300
338
  def _set_value(key, value)
301
- raise NullError.build(key) if @attributes.nil?
302
- raise ArrayError.build(key) if ::Array === @attributes
339
+ ::Kernel.raise NullError.build(key) if @attributes.nil?
340
+ ::Kernel.raise ArrayError.build(key) if ::Array === @attributes
303
341
  return if @ignore_nil && value.nil? or _blank?(value)
304
342
  @attributes = {} if _blank?
305
343
  @attributes[_key(key)] = value
@@ -312,25 +350,21 @@ class Jbuilder
312
350
  end
313
351
 
314
352
  def _scope
315
- parent_attributes, parent_formatter = @attributes, @key_formatter
353
+ parent_attributes, parent_formatter, parent_deep_format_keys = @attributes, @key_formatter, @deep_format_keys
316
354
  @attributes = BLANK
317
355
  yield
318
356
  @attributes
319
357
  ensure
320
- @attributes, @key_formatter = parent_attributes, parent_formatter
358
+ @attributes, @key_formatter, @deep_format_keys = parent_attributes, parent_formatter, parent_deep_format_keys
321
359
  end
322
360
 
323
361
  def _is_collection?(object)
324
- _object_respond_to?(object, :map, :count) && NON_ENUMERABLES.none?{ |klass| klass === object }
362
+ object.respond_to?(:map) && object.respond_to?(:count) && !(::Struct === object)
325
363
  end
326
364
 
327
365
  def _blank?(value=@attributes)
328
366
  BLANK == value
329
367
  end
330
-
331
- def _object_respond_to?(object, *methods)
332
- methods.all?{ |m| object.respond_to?(m) }
333
- end
334
368
  end
335
369
 
336
370
  require 'jbuilder/railtie' if defined?(Rails)
@@ -1,6 +1,5 @@
1
1
  require 'test_helper'
2
- require 'jbuilder/dependency_tracker'
3
-
2
+ require 'jbuilder/jbuilder_dependency_tracker'
4
3
 
5
4
  class FakeTemplate
6
5
  attr_reader :source, :handler
@@ -61,7 +60,7 @@ class JbuilderDependencyTrackerTest < ActiveSupport::TestCase
61
60
  assert_equal %w[comments/comment], dependencies
62
61
  end
63
62
 
64
- test 'detects explicit depedency' do
63
+ test 'detects explicit dependency' do
65
64
  dependencies = track_dependencies <<-RUBY
66
65
  # Template Dependency: path/to/partial
67
66
  json.foo 'bar'
@@ -44,15 +44,25 @@ class JbuilderGeneratorTest < Rails::Generators::TestCase
44
44
  end
45
45
  end
46
46
 
47
- if Rails::VERSION::MAJOR >= 6
48
- test 'handles virtual attributes' do
49
- run_generator %w(Message content:rich_text video:attachment photos:attachments)
50
-
51
- assert_file 'app/views/messages/_message.json.jbuilder' do |content|
52
- assert_match %r{json\.content message\.content\.to_s}, content
53
- assert_match %r{json\.video url_for\(message\.video\)}, content
54
- assert_match %r{json\.photos do\n json\.array!\(message\.photos\) do \|photo\|\n json\.id photo\.id\n json\.url url_for\(photo\)\n end\nend}, content
55
- end
47
+ test 'namespaced views are generated correctly for index' do
48
+ run_generator %w(Admin::Post --model-name=Post)
49
+
50
+ assert_file 'app/views/admin/posts/index.json.jbuilder' do |content|
51
+ assert_match %r{json\.array! @posts, partial: "admin/posts/post", as: :post}, content
52
+ end
53
+
54
+ assert_file 'app/views/admin/posts/show.json.jbuilder' do |content|
55
+ assert_match %r{json\.partial! "admin/posts/post", post: @post}, content
56
+ end
57
+ end
58
+
59
+ test 'handles virtual attributes' do
60
+ run_generator %w(Message content:rich_text video:attachment photos:attachments)
61
+
62
+ assert_file 'app/views/messages/_message.json.jbuilder' do |content|
63
+ assert_match %r{json\.content message\.content\.to_s}, content
64
+ assert_match %r{json\.video url_for\(message\.video\)}, content
65
+ assert_match %r{json\.photos do\n json\.array!\(message\.photos\) do \|photo\|\n json\.id photo\.id\n json\.url url_for\(photo\)\n end\nend}, content
56
66
  end
57
67
  end
58
68
  end
@@ -49,6 +49,17 @@ class JbuilderTemplateTest < ActiveSupport::TestCase
49
49
  assert_equal "hello", result["content"]
50
50
  end
51
51
 
52
+ test "partial by name with hash value omission (punning) as last statement [3.1+]" do
53
+ major, minor, _ = RUBY_VERSION.split(".").map(&:to_i)
54
+ return unless (major == 3 && minor >= 1) || major > 3
55
+
56
+ result = render(<<-JBUILDER)
57
+ content = "hello"
58
+ json.partial! "partial", content:
59
+ JBUILDER
60
+ assert_equal "hello", result["content"]
61
+ end
62
+
52
63
  test "partial by options containing nested locals" do
53
64
  result = render('json.partial! partial: "partial", locals: { content: "hello" }')
54
65
  assert_equal "hello", result["content"]
@@ -73,6 +84,14 @@ class JbuilderTemplateTest < ActiveSupport::TestCase
73
84
  assert_equal "Pavel", result[5]["author"]["first_name"]
74
85
  end
75
86
 
87
+ test "partial collection by name with caching" do
88
+ result = render('json.partial! "post", collection: @posts, cached: true, as: :post', posts: POSTS)
89
+ assert_equal 10, result.count
90
+ assert_equal "Post #5", result[4]["body"]
91
+ assert_equal "Heinemeier Hansson", result[2]["author"]["last_name"]
92
+ assert_equal "Pavel", result[5]["author"]["first_name"]
93
+ end
94
+
76
95
  test "partial collection by name with string local" do
77
96
  result = render('json.partial! "post", collection: @posts, as: "post"', posts: POSTS)
78
97
  assert_equal 10, result.count
@@ -90,10 +109,12 @@ class JbuilderTemplateTest < ActiveSupport::TestCase
90
109
  end
91
110
 
92
111
  test "nil partial collection by name" do
112
+ Jbuilder::CollectionRenderer.expects(:new).never
93
113
  assert_equal [], render('json.partial! "post", collection: @posts, as: :post', posts: nil)
94
114
  end
95
115
 
96
116
  test "nil partial collection by options" do
117
+ Jbuilder::CollectionRenderer.expects(:new).never
97
118
  assert_equal [], render('json.partial! partial: "post", collection: @posts, as: :post', posts: nil)
98
119
  end
99
120
 
@@ -105,7 +126,13 @@ class JbuilderTemplateTest < ActiveSupport::TestCase
105
126
  assert_equal "Pavel", result[5]["author"]["first_name"]
106
127
  end
107
128
 
129
+ test "empty array of partials from empty collection" do
130
+ Jbuilder::CollectionRenderer.expects(:new).never
131
+ assert_equal [], render('json.array! @posts, partial: "post", as: :post', posts: [])
132
+ end
133
+
108
134
  test "empty array of partials from nil collection" do
135
+ Jbuilder::CollectionRenderer.expects(:new).never
109
136
  assert_equal [], render('json.array! @posts, partial: "post", as: :post', posts: nil)
110
137
  end
111
138
 
@@ -118,10 +145,17 @@ class JbuilderTemplateTest < ActiveSupport::TestCase
118
145
  end
119
146
 
120
147
  test "empty array of partials under key from nil collection" do
148
+ Jbuilder::CollectionRenderer.expects(:new).never
121
149
  result = render('json.posts @posts, partial: "post", as: :post', posts: nil)
122
150
  assert_equal [], result["posts"]
123
151
  end
124
152
 
153
+ test "empty array of partials under key from an empy collection" do
154
+ Jbuilder::CollectionRenderer.expects(:new).never
155
+ result = render('json.posts @posts, partial: "post", as: :post', posts: [])
156
+ assert_equal [], result["posts"]
157
+ end
158
+
125
159
  test "object fragment caching" do
126
160
  render(<<-JBUILDER)
127
161
  json.cache! "cache-key" do
@@ -159,7 +193,7 @@ class JbuilderTemplateTest < ActiveSupport::TestCase
159
193
  end
160
194
 
161
195
  test "object fragment caching with expiry" do
162
- travel_to "2018-05-12 11:29:00 -0400"
196
+ travel_to Time.iso8601("2018-05-12T11:29:00-04:00")
163
197
 
164
198
  render <<-JBUILDER
165
199
  json.cache! "cache-key", expires_in: 1.minute do
@@ -283,6 +317,99 @@ class JbuilderTemplateTest < ActiveSupport::TestCase
283
317
  assert_equal "David", result["firstName"]
284
318
  end
285
319
 
320
+ test "returns an empty array for an empty collection" do
321
+ Jbuilder::CollectionRenderer.expects(:new).never
322
+ result = render('json.array! @posts, partial: "post", as: :post, cached: true', posts: [])
323
+
324
+ # Do not use #assert_empty as it is important to ensure that the type of the JSON result is an array.
325
+ assert_equal [], result
326
+ end
327
+
328
+ test "works with an enumerable object" do
329
+ enumerable_class = Class.new do
330
+ include Enumerable
331
+
332
+ def each(&block)
333
+ [].each(&block)
334
+ end
335
+ end
336
+
337
+ result = render('json.array! @posts, partial: "post", as: :post, cached: true', posts: enumerable_class.new)
338
+
339
+ # Do not use #assert_empty as it is important to ensure that the type of the JSON result is an array.
340
+ assert_equal [], result
341
+ end
342
+
343
+ test "supports the cached: true option" do
344
+ result = render('json.array! @posts, partial: "post", as: :post, cached: true', posts: POSTS)
345
+
346
+ assert_equal 10, result.count
347
+ assert_equal "Post #5", result[4]["body"]
348
+ assert_equal "Heinemeier Hansson", result[2]["author"]["last_name"]
349
+ assert_equal "Pavel", result[5]["author"]["first_name"]
350
+
351
+ expected = {
352
+ "id" => 1,
353
+ "body" => "Post #1",
354
+ "author" => {
355
+ "first_name" => "David",
356
+ "last_name" => "Heinemeier Hansson"
357
+ }
358
+ }
359
+
360
+ assert_equal expected, Rails.cache.read("post-1")
361
+
362
+ result = render('json.array! @posts, partial: "post", as: :post, cached: true', posts: POSTS)
363
+
364
+ assert_equal 10, result.count
365
+ assert_equal "Post #5", result[4]["body"]
366
+ assert_equal "Heinemeier Hansson", result[2]["author"]["last_name"]
367
+ assert_equal "Pavel", result[5]["author"]["first_name"]
368
+ end
369
+
370
+ test "supports the cached: ->() {} option" do
371
+ result = render('json.array! @posts, partial: "post", as: :post, cached: ->(post) { [post, "foo"] }', posts: POSTS)
372
+
373
+ assert_equal 10, result.count
374
+ assert_equal "Post #5", result[4]["body"]
375
+ assert_equal "Heinemeier Hansson", result[2]["author"]["last_name"]
376
+ assert_equal "Pavel", result[5]["author"]["first_name"]
377
+
378
+ expected = {
379
+ "id" => 1,
380
+ "body" => "Post #1",
381
+ "author" => {
382
+ "first_name" => "David",
383
+ "last_name" => "Heinemeier Hansson"
384
+ }
385
+ }
386
+
387
+ assert_equal expected, Rails.cache.read("post-1/foo")
388
+
389
+ result = render('json.array! @posts, partial: "post", as: :post, cached: ->(post) { [post, "foo"] }', posts: POSTS)
390
+
391
+ assert_equal 10, result.count
392
+ assert_equal "Post #5", result[4]["body"]
393
+ assert_equal "Heinemeier Hansson", result[2]["author"]["last_name"]
394
+ assert_equal "Pavel", result[5]["author"]["first_name"]
395
+ end
396
+
397
+ test "raises an error on a render call with the :layout option" do
398
+ error = assert_raises NotImplementedError do
399
+ render('json.array! @posts, partial: "post", as: :post, layout: "layout"', posts: POSTS)
400
+ end
401
+
402
+ assert_equal "The `:layout' option is not supported in collection rendering.", error.message
403
+ end
404
+
405
+ test "raises an error on a render call with the :spacer_template option" do
406
+ error = assert_raises NotImplementedError do
407
+ render('json.array! @posts, partial: "post", as: :post, spacer_template: "template"', posts: POSTS)
408
+ end
409
+
410
+ assert_equal "The `:spacer_template' option is not supported in collection rendering.", error.message
411
+ end
412
+
286
413
  private
287
414
  def render(*args)
288
415
  JSON.load render_without_parsing(*args)
@@ -290,7 +417,7 @@ class JbuilderTemplateTest < ActiveSupport::TestCase
290
417
 
291
418
  def render_without_parsing(source, assigns = {})
292
419
  view = build_view(fixtures: PARTIALS.merge("source.json.jbuilder" => source), assigns: assigns)
293
- view.render(template: "source.json.jbuilder")
420
+ view.render(template: "source")
294
421
  end
295
422
 
296
423
  def build_view(options = {})
@@ -298,14 +425,12 @@ class JbuilderTemplateTest < ActiveSupport::TestCase
298
425
  lookup_context = ActionView::LookupContext.new([ resolver ], {}, [""])
299
426
  controller = ActionView::TestCase::TestController.new
300
427
 
301
- # TODO: Use with_empty_template_cache unconditionally after dropping support for Rails <6.0.
302
- view = if ActionView::Base.respond_to?(:with_empty_template_cache)
303
- ActionView::Base.with_empty_template_cache.new(lookup_context, options.fetch(:assigns, {}), controller)
304
- else
305
- ActionView::Base.new(lookup_context, options.fetch(:assigns, {}), controller)
306
- end
428
+ view = ActionView::Base.with_empty_template_cache.new(lookup_context, options.fetch(:assigns, {}), controller)
307
429
 
308
430
  def view.view_cache_dependencies; []; end
431
+ def view.combined_fragment_cache_key(key) [ key ] end
432
+ def view.cache_fragment_name(key, *) key end
433
+ def view.fragment_name_with_digest(key) key end
309
434
 
310
435
  view
311
436
  end