jbuilder 2.0.6 → 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.
- checksums.yaml +5 -5
- data/.github/workflows/ruby.yml +108 -0
- data/.gitignore +4 -1
- data/Appraisals +25 -0
- data/CONTRIBUTING.md +106 -0
- data/Gemfile +4 -12
- data/MIT-LICENSE +1 -1
- data/README.md +171 -45
- data/Rakefile +15 -10
- data/gemfiles/rails_5_0.gemfile +10 -0
- data/gemfiles/rails_5_1.gemfile +10 -0
- data/gemfiles/rails_5_2.gemfile +10 -0
- data/gemfiles/rails_6_0.gemfile +10 -0
- data/gemfiles/rails_6_1.gemfile +10 -0
- data/gemfiles/rails_head.gemfile +10 -0
- data/jbuilder.gemspec +20 -6
- data/lib/generators/rails/jbuilder_generator.rb +13 -2
- data/lib/generators/rails/scaffold_controller_generator.rb +9 -3
- data/lib/generators/rails/templates/api_controller.rb +63 -0
- data/lib/generators/rails/templates/controller.rb +16 -20
- data/lib/generators/rails/templates/index.json.jbuilder +1 -4
- data/lib/generators/rails/templates/partial.json.jbuilder +16 -0
- data/lib/generators/rails/templates/show.json.jbuilder +1 -1
- data/lib/jbuilder/blank.rb +11 -0
- data/lib/jbuilder/collection_renderer.rb +109 -0
- data/lib/jbuilder/dependency_tracker.rb +1 -1
- data/lib/jbuilder/errors.rb +24 -0
- data/lib/jbuilder/jbuilder.rb +7 -0
- data/lib/jbuilder/jbuilder_template.rb +213 -65
- data/lib/jbuilder/key_formatter.rb +34 -0
- data/lib/jbuilder/railtie.rb +31 -6
- data/lib/jbuilder.rb +148 -114
- data/test/jbuilder_dependency_tracker_test.rb +3 -4
- data/test/jbuilder_generator_test.rb +31 -4
- data/test/jbuilder_template_test.rb +313 -195
- data/test/jbuilder_test.rb +615 -219
- data/test/scaffold_api_controller_generator_test.rb +70 -0
- data/test/scaffold_controller_generator_test.rb +62 -19
- data/test/test_helper.rb +36 -0
- metadata +38 -23
- data/.travis.yml +0 -21
- data/CHANGELOG.md +0 -89
- data/Gemfile.old +0 -14
@@ -1,292 +1,410 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
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) }
|
34
|
+
|
35
|
+
setup { Rails.cache.clear }
|
36
|
+
|
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
|
-
|
19
|
-
|
20
|
-
|
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
|
-
|
23
|
-
|
24
|
-
|
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
|
-
|
29
|
-
|
30
|
-
|
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
|
-
|
35
|
-
|
36
|
-
|
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
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
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
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
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
|
-
|
56
|
-
result =
|
57
|
-
|
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
|
-
|
60
|
-
|
61
|
-
assert_equal
|
62
|
-
assert_equal
|
63
|
-
assert_equal
|
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
|
67
|
-
json
|
68
|
-
|
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
|
-
|
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
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
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
|
-
|
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
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
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
|
-
|
93
|
-
|
94
|
-
assert_equal
|
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
|
98
|
-
|
99
|
-
json.
|
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
|
-
|
132
|
+
hit = render('json.cache! "cache-key" do; end')
|
133
|
+
assert_equal "Hit", hit["name"]
|
103
134
|
end
|
104
135
|
|
105
|
-
test
|
106
|
-
|
107
|
-
json.
|
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
|
-
|
111
|
-
|
147
|
+
result = render(<<-JBUILDER)
|
148
|
+
json.cache_if! true, "cache-key" do
|
149
|
+
json.a "Miss"
|
150
|
+
end
|
112
151
|
|
113
|
-
|
114
|
-
|
115
|
-
|
152
|
+
json.cache_if! false, "cache-key" do
|
153
|
+
json.b "Miss"
|
154
|
+
end
|
116
155
|
JBUILDER
|
117
156
|
|
118
|
-
assert_equal
|
157
|
+
assert_equal "Hit", result["a"]
|
158
|
+
assert_equal "Miss", result["b"]
|
119
159
|
end
|
120
160
|
|
121
|
-
test
|
122
|
-
|
123
|
-
|
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
|
-
|
127
|
-
end
|
170
|
+
travel 30.seconds
|
128
171
|
|
129
|
-
|
130
|
-
|
131
|
-
|
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
|
135
|
-
|
178
|
+
assert_equal "Hit", result["name"]
|
179
|
+
|
180
|
+
travel 31.seconds
|
136
181
|
|
137
|
-
|
138
|
-
|
139
|
-
|
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
|
-
|
188
|
+
assert_equal "Miss", result["name"]
|
143
189
|
end
|
144
190
|
|
145
|
-
test
|
146
|
-
|
147
|
-
json.
|
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
|
151
|
-
end
|
198
|
+
assert_equal JSON.dump(name: "Hit"), Rails.cache.read("jbuilder/root/cache-key")
|
152
199
|
|
153
|
-
|
154
|
-
|
155
|
-
|
200
|
+
result = render(<<-JBUILDER)
|
201
|
+
json.cache_root! "cache-key" do
|
202
|
+
json.name "Miss"
|
203
|
+
end
|
156
204
|
JBUILDER
|
157
205
|
|
158
|
-
|
206
|
+
assert_equal "Hit", result["name"]
|
159
207
|
end
|
160
208
|
|
161
|
-
test
|
162
|
-
|
163
|
-
json.
|
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
|
216
|
+
assert_equal %w[ a b c ], render('json.cache! "cache-key" do; end')
|
167
217
|
end
|
168
218
|
|
169
|
-
test
|
170
|
-
|
171
|
-
|
172
|
-
|
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
|
-
|
179
|
-
|
180
|
-
|
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
|
-
|
185
|
-
|
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
|
189
|
-
|
246
|
+
test "empty fragment caching" do
|
247
|
+
render 'json.cache! "nothing" do; end'
|
190
248
|
|
191
|
-
|
192
|
-
json.cache_if! true, 'cachekey' do
|
193
|
-
json.test1 'Cache'
|
194
|
-
end
|
195
|
-
json.cache_if! false, 'cachekey' do
|
196
|
-
json.test2 'Cache'
|
197
|
-
end
|
198
|
-
JBUILDER
|
249
|
+
result = nil
|
199
250
|
|
200
|
-
|
201
|
-
|
202
|
-
json.
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
end
|
207
|
-
JBUILDER
|
251
|
+
assert_nothing_raised do
|
252
|
+
result = render(<<-JBUILDER)
|
253
|
+
json.foo "bar"
|
254
|
+
json.cache! "nothing" do; end
|
255
|
+
JBUILDER
|
256
|
+
end
|
208
257
|
|
209
|
-
|
210
|
-
assert_equal 'Cache', parsed['test1']
|
211
|
-
assert_equal 'Miss', parsed['test2']
|
258
|
+
assert_equal "bar", result["foo"]
|
212
259
|
end
|
213
260
|
|
214
|
-
test
|
215
|
-
|
261
|
+
test "cache instrumentation" do
|
262
|
+
payloads = {}
|
216
263
|
|
217
|
-
|
218
|
-
|
219
|
-
|
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"
|
220
270
|
end
|
221
271
|
JBUILDER
|
222
272
|
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
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"
|
227
281
|
JBUILDER
|
228
282
|
|
229
|
-
|
230
|
-
assert_equal %w(a b c), parsed
|
283
|
+
assert_equal "David", result["firstName"]
|
231
284
|
end
|
232
285
|
|
233
|
-
|
234
|
-
|
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: [])
|
289
|
+
|
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
|
235
293
|
|
236
|
-
|
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.
|
237
298
|
|
238
|
-
|
239
|
-
|
240
|
-
|
299
|
+
def each(&block)
|
300
|
+
[].each(&block)
|
301
|
+
end
|
241
302
|
end
|
242
|
-
JBUILDER
|
243
|
-
end
|
244
303
|
|
245
|
-
|
246
|
-
undef_context_methods :fragment_name_with_digest
|
304
|
+
result = render('json.array! @posts, partial: "post", as: :post, cached: true', posts: enumerable_class.new)
|
247
305
|
|
248
|
-
|
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
|
249
309
|
|
250
|
-
|
251
|
-
json.
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
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
|
+
}
|
256
326
|
|
257
|
-
|
258
|
-
undef_context_methods :fragment_name_with_digest
|
327
|
+
assert_equal expected, Rails.cache.read("post-1")
|
259
328
|
|
260
|
-
|
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
|
261
336
|
|
262
|
-
|
263
|
-
json.
|
264
|
-
|
337
|
+
test "supports the cached: ->() {} option" do
|
338
|
+
result = render('json.array! @posts, partial: "post", as: :post, cached: ->(post) { [post, "foo"] }', posts: POSTS)
|
339
|
+
|
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)
|
265
367
|
end
|
266
|
-
JBUILDER
|
267
|
-
end
|
268
368
|
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
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)
|
274
375
|
end
|
275
|
-
JBUILDER
|
276
376
|
|
277
|
-
|
377
|
+
assert_equal "The `:spacer_template' option is not supported in collection rendering.", error.message
|
378
|
+
end
|
278
379
|
end
|
279
380
|
|
280
|
-
|
281
|
-
|
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
|
282
390
|
|
283
|
-
|
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
|
284
395
|
|
285
|
-
|
286
|
-
|
287
|
-
|
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)
|
288
401
|
end
|
289
|
-
JBUILDER
|
290
|
-
end
|
291
402
|
|
292
|
-
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
|