jbuilder 2.11.1 → 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 +4 -4
- data/.github/workflows/ruby.yml +108 -0
- data/Appraisals +5 -1
- data/CONTRIBUTING.md +3 -3
- data/README.md +73 -9
- data/Rakefile +1 -1
- data/gemfiles/rails_6_1.gemfile +10 -0
- data/gemfiles/rails_head.gemfile +1 -1
- data/jbuilder.gemspec +10 -1
- data/lib/generators/rails/templates/controller.rb +3 -2
- data/lib/jbuilder/collection_renderer.rb +109 -0
- data/lib/jbuilder/jbuilder_template.rb +54 -7
- data/lib/jbuilder/railtie.rb +1 -1
- data/lib/jbuilder.rb +40 -10
- data/test/jbuilder_dependency_tracker_test.rb +1 -1
- data/test/jbuilder_template_test.rb +100 -2
- data/test/jbuilder_test.rb +139 -6
- data/test/scaffold_api_controller_generator_test.rb +1 -1
- data/test/scaffold_controller_generator_test.rb +22 -3
- data/test/test_helper.rb +11 -9
- metadata +26 -6
- data/.travis.yml +0 -52
- data/CHANGELOG.md +0 -306
data/lib/jbuilder.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'active_support'
|
1
2
|
require 'jbuilder/jbuilder'
|
2
3
|
require 'jbuilder/blank'
|
3
4
|
require 'jbuilder/key_formatter'
|
@@ -9,12 +10,14 @@ require 'active_support/core_ext/hash/deep_merge'
|
|
9
10
|
class Jbuilder
|
10
11
|
@@key_formatter = nil
|
11
12
|
@@ignore_nil = false
|
13
|
+
@@deep_format_keys = false
|
12
14
|
|
13
15
|
def initialize(options = {})
|
14
16
|
@attributes = {}
|
15
17
|
|
16
18
|
@key_formatter = options.fetch(:key_formatter){ @@key_formatter ? @@key_formatter.clone : nil}
|
17
19
|
@ignore_nil = options.fetch(:ignore_nil, @@ignore_nil)
|
20
|
+
@deep_format_keys = options.fetch(:deep_format_keys, @@deep_format_keys)
|
18
21
|
|
19
22
|
yield self if ::Kernel.block_given?
|
20
23
|
end
|
@@ -131,6 +134,31 @@ class Jbuilder
|
|
131
134
|
@@ignore_nil = value
|
132
135
|
end
|
133
136
|
|
137
|
+
# Deeply apply key format to nested hashes and arrays passed to
|
138
|
+
# methods like set!, merge! or array!.
|
139
|
+
#
|
140
|
+
# Example:
|
141
|
+
#
|
142
|
+
# json.key_format! camelize: :lower
|
143
|
+
# json.settings({some_value: "abc"})
|
144
|
+
#
|
145
|
+
# { "settings": { "some_value": "abc" }}
|
146
|
+
#
|
147
|
+
# json.key_format! camelize: :lower
|
148
|
+
# json.deep_format_keys!
|
149
|
+
# json.settings({some_value: "abc"})
|
150
|
+
#
|
151
|
+
# { "settings": { "someValue": "abc" }}
|
152
|
+
#
|
153
|
+
def deep_format_keys!(value = true)
|
154
|
+
@deep_format_keys = value
|
155
|
+
end
|
156
|
+
|
157
|
+
# Same as instance method deep_format_keys! except sets the default.
|
158
|
+
def self.deep_format_keys(value = true)
|
159
|
+
@@deep_format_keys = value
|
160
|
+
end
|
161
|
+
|
134
162
|
# Turns the current element into an array and yields a builder to add a hash.
|
135
163
|
#
|
136
164
|
# Example:
|
@@ -190,10 +218,10 @@ class Jbuilder
|
|
190
218
|
elsif attributes.any?
|
191
219
|
_map_collection(collection) { |element| extract! element, *attributes }
|
192
220
|
else
|
193
|
-
collection.to_a
|
221
|
+
_format_keys(collection.to_a)
|
194
222
|
end
|
195
223
|
|
196
|
-
|
224
|
+
@attributes = _merge_values(@attributes, array)
|
197
225
|
end
|
198
226
|
|
199
227
|
# Extracts the mentioned attributes or hash elements from the passed object and turns them into attributes of the JSON.
|
@@ -244,7 +272,7 @@ class Jbuilder
|
|
244
272
|
# Merges hash, array, or Jbuilder instance into current builder.
|
245
273
|
def merge!(object)
|
246
274
|
hash_or_array = ::Jbuilder === object ? object.attributes! : object
|
247
|
-
@attributes = _merge_values(@attributes, hash_or_array)
|
275
|
+
@attributes = _merge_values(@attributes, _format_keys(hash_or_array))
|
248
276
|
end
|
249
277
|
|
250
278
|
# Encodes the current builder as JSON.
|
@@ -255,11 +283,11 @@ class Jbuilder
|
|
255
283
|
private
|
256
284
|
|
257
285
|
def _extract_hash_values(object, attributes)
|
258
|
-
attributes.each{ |key| _set_value key, object.fetch(key) }
|
286
|
+
attributes.each{ |key| _set_value key, _format_keys(object.fetch(key)) }
|
259
287
|
end
|
260
288
|
|
261
289
|
def _extract_method_values(object, attributes)
|
262
|
-
attributes.each{ |key| _set_value key, object.public_send(key) }
|
290
|
+
attributes.each{ |key| _set_value key, _format_keys(object.public_send(key)) }
|
263
291
|
end
|
264
292
|
|
265
293
|
def _merge_block(key)
|
@@ -273,11 +301,11 @@ class Jbuilder
|
|
273
301
|
if _blank?(updates)
|
274
302
|
current_value
|
275
303
|
elsif _blank?(current_value) || updates.nil? || current_value.empty? && ::Array === updates
|
276
|
-
|
304
|
+
updates
|
277
305
|
elsif ::Array === current_value && ::Array === updates
|
278
|
-
current_value +
|
306
|
+
current_value + updates
|
279
307
|
elsif ::Hash === current_value && ::Hash === updates
|
280
|
-
current_value.deep_merge(
|
308
|
+
current_value.deep_merge(updates)
|
281
309
|
else
|
282
310
|
raise MergeError.build(current_value, updates)
|
283
311
|
end
|
@@ -288,6 +316,8 @@ class Jbuilder
|
|
288
316
|
end
|
289
317
|
|
290
318
|
def _format_keys(hash_or_array)
|
319
|
+
return hash_or_array unless @deep_format_keys
|
320
|
+
|
291
321
|
if ::Array === hash_or_array
|
292
322
|
hash_or_array.map { |value| _format_keys(value) }
|
293
323
|
elsif ::Hash === hash_or_array
|
@@ -312,12 +342,12 @@ class Jbuilder
|
|
312
342
|
end
|
313
343
|
|
314
344
|
def _scope
|
315
|
-
parent_attributes, parent_formatter = @attributes, @key_formatter
|
345
|
+
parent_attributes, parent_formatter, parent_deep_format_keys = @attributes, @key_formatter, @deep_format_keys
|
316
346
|
@attributes = BLANK
|
317
347
|
yield
|
318
348
|
@attributes
|
319
349
|
ensure
|
320
|
-
@attributes, @key_formatter = parent_attributes, parent_formatter
|
350
|
+
@attributes, @key_formatter, @deep_format_keys = parent_attributes, parent_formatter, parent_deep_format_keys
|
321
351
|
end
|
322
352
|
|
323
353
|
def _is_collection?(object)
|
@@ -61,7 +61,7 @@ class JbuilderDependencyTrackerTest < ActiveSupport::TestCase
|
|
61
61
|
assert_equal %w[comments/comment], dependencies
|
62
62
|
end
|
63
63
|
|
64
|
-
test 'detects explicit
|
64
|
+
test 'detects explicit dependency' do
|
65
65
|
dependencies = track_dependencies <<-RUBY
|
66
66
|
# Template Dependency: path/to/partial
|
67
67
|
json.foo 'bar'
|
@@ -159,7 +159,7 @@ class JbuilderTemplateTest < ActiveSupport::TestCase
|
|
159
159
|
end
|
160
160
|
|
161
161
|
test "object fragment caching with expiry" do
|
162
|
-
travel_to "2018-05-
|
162
|
+
travel_to Time.iso8601("2018-05-12T11:29:00-04:00")
|
163
163
|
|
164
164
|
render <<-JBUILDER
|
165
165
|
json.cache! "cache-key", expires_in: 1.minute do
|
@@ -283,6 +283,101 @@ class JbuilderTemplateTest < ActiveSupport::TestCase
|
|
283
283
|
assert_equal "David", result["firstName"]
|
284
284
|
end
|
285
285
|
|
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
|
293
|
+
|
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
|
302
|
+
end
|
303
|
+
|
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
|
336
|
+
|
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)
|
367
|
+
end
|
368
|
+
|
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)
|
375
|
+
end
|
376
|
+
|
377
|
+
assert_equal "The `:spacer_template' option is not supported in collection rendering.", error.message
|
378
|
+
end
|
379
|
+
end
|
380
|
+
|
286
381
|
private
|
287
382
|
def render(*args)
|
288
383
|
JSON.load render_without_parsing(*args)
|
@@ -290,7 +385,7 @@ class JbuilderTemplateTest < ActiveSupport::TestCase
|
|
290
385
|
|
291
386
|
def render_without_parsing(source, assigns = {})
|
292
387
|
view = build_view(fixtures: PARTIALS.merge("source.json.jbuilder" => source), assigns: assigns)
|
293
|
-
view.render(template: "source
|
388
|
+
view.render(template: "source")
|
294
389
|
end
|
295
390
|
|
296
391
|
def build_view(options = {})
|
@@ -306,6 +401,9 @@ class JbuilderTemplateTest < ActiveSupport::TestCase
|
|
306
401
|
end
|
307
402
|
|
308
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
|
309
407
|
|
310
408
|
view
|
311
409
|
end
|
data/test/jbuilder_test.rb
CHANGED
@@ -312,7 +312,7 @@ class JbuilderTest < ActiveSupport::TestCase
|
|
312
312
|
assert_equal 'world', result['comments'].second['content']
|
313
313
|
end
|
314
314
|
|
315
|
-
test 'nesting multiple
|
315
|
+
test 'nesting multiple children from a non-Enumerable that responds to #map with inline loop' do
|
316
316
|
comments = NonEnumerable.new([ Comment.new('hello', 1), Comment.new('world', 2) ])
|
317
317
|
|
318
318
|
result = jbuild do |json|
|
@@ -566,6 +566,36 @@ class JbuilderTest < ActiveSupport::TestCase
|
|
566
566
|
assert_equal 'one', result['level1']
|
567
567
|
end
|
568
568
|
|
569
|
+
test 'key_format! can be changed in child elements' do
|
570
|
+
result = jbuild do |json|
|
571
|
+
json.key_format! camelize: :lower
|
572
|
+
|
573
|
+
json.level_one do
|
574
|
+
json.key_format! :upcase
|
575
|
+
json.value 'two'
|
576
|
+
end
|
577
|
+
end
|
578
|
+
|
579
|
+
assert_equal ['levelOne'], result.keys
|
580
|
+
assert_equal ['VALUE'], result['levelOne'].keys
|
581
|
+
end
|
582
|
+
|
583
|
+
test 'key_format! can be changed in array!' do
|
584
|
+
result = jbuild do |json|
|
585
|
+
json.key_format! camelize: :lower
|
586
|
+
|
587
|
+
json.level_one do
|
588
|
+
json.array! [{value: 'two'}] do |object|
|
589
|
+
json.key_format! :upcase
|
590
|
+
json.value object[:value]
|
591
|
+
end
|
592
|
+
end
|
593
|
+
end
|
594
|
+
|
595
|
+
assert_equal ['levelOne'], result.keys
|
596
|
+
assert_equal ['VALUE'], result['levelOne'][0].keys
|
597
|
+
end
|
598
|
+
|
569
599
|
test 'key_format! with no parameter' do
|
570
600
|
result = jbuild do |json|
|
571
601
|
json.key_format! :upcase
|
@@ -593,51 +623,121 @@ class JbuilderTest < ActiveSupport::TestCase
|
|
593
623
|
assert_equal ['oats and friends'], result.keys
|
594
624
|
end
|
595
625
|
|
596
|
-
test 'key_format!
|
626
|
+
test 'key_format! is not applied deeply by default' do
|
627
|
+
names = { first_name: 'camel', last_name: 'case' }
|
628
|
+
result = jbuild do |json|
|
629
|
+
json.key_format! camelize: :lower
|
630
|
+
json.set! :all_names, names
|
631
|
+
end
|
632
|
+
|
633
|
+
assert_equal %i[first_name last_name], result['allNames'].keys
|
634
|
+
end
|
635
|
+
|
636
|
+
test 'applying key_format! deeply can be enabled per scope' do
|
637
|
+
names = { first_name: 'camel', last_name: 'case' }
|
638
|
+
result = jbuild do |json|
|
639
|
+
json.key_format! camelize: :lower
|
640
|
+
json.scope do
|
641
|
+
json.deep_format_keys!
|
642
|
+
json.set! :all_names, names
|
643
|
+
end
|
644
|
+
json.set! :all_names, names
|
645
|
+
end
|
646
|
+
|
647
|
+
assert_equal %w[firstName lastName], result['scope']['allNames'].keys
|
648
|
+
assert_equal %i[first_name last_name], result['allNames'].keys
|
649
|
+
end
|
650
|
+
|
651
|
+
test 'applying key_format! deeply can be disabled per scope' do
|
652
|
+
names = { first_name: 'camel', last_name: 'case' }
|
653
|
+
result = jbuild do |json|
|
654
|
+
json.key_format! camelize: :lower
|
655
|
+
json.deep_format_keys!
|
656
|
+
json.set! :all_names, names
|
657
|
+
json.scope do
|
658
|
+
json.deep_format_keys! false
|
659
|
+
json.set! :all_names, names
|
660
|
+
end
|
661
|
+
end
|
662
|
+
|
663
|
+
assert_equal %w[firstName lastName], result['allNames'].keys
|
664
|
+
assert_equal %i[first_name last_name], result['scope']['allNames'].keys
|
665
|
+
end
|
666
|
+
|
667
|
+
test 'applying key_format! deeply can be enabled globally' do
|
668
|
+
names = { first_name: 'camel', last_name: 'case' }
|
669
|
+
|
670
|
+
Jbuilder.deep_format_keys true
|
671
|
+
result = jbuild do |json|
|
672
|
+
json.key_format! camelize: :lower
|
673
|
+
json.set! :all_names, names
|
674
|
+
end
|
675
|
+
|
676
|
+
assert_equal %w[firstName lastName], result['allNames'].keys
|
677
|
+
Jbuilder.send(:class_variable_set, '@@deep_format_keys', false)
|
678
|
+
end
|
679
|
+
|
680
|
+
test 'deep key_format! with merge!' do
|
597
681
|
hash = { camel_style: 'for JS' }
|
598
682
|
result = jbuild do |json|
|
599
683
|
json.key_format! camelize: :lower
|
684
|
+
json.deep_format_keys!
|
600
685
|
json.merge! hash
|
601
686
|
end
|
602
687
|
|
603
688
|
assert_equal ['camelStyle'], result.keys
|
604
689
|
end
|
605
690
|
|
606
|
-
test 'key_format! with merge! deep' do
|
691
|
+
test 'deep key_format! with merge! deep' do
|
607
692
|
hash = { camel_style: { sub_attr: 'for JS' } }
|
608
693
|
result = jbuild do |json|
|
609
694
|
json.key_format! camelize: :lower
|
695
|
+
json.deep_format_keys!
|
610
696
|
json.merge! hash
|
611
697
|
end
|
612
698
|
|
613
699
|
assert_equal ['subAttr'], result['camelStyle'].keys
|
614
700
|
end
|
615
701
|
|
616
|
-
test 'key_format! with set! array of hashes' do
|
702
|
+
test 'deep key_format! with set! array of hashes' do
|
617
703
|
names = [{ first_name: 'camel', last_name: 'case' }]
|
618
704
|
result = jbuild do |json|
|
619
705
|
json.key_format! camelize: :lower
|
706
|
+
json.deep_format_keys!
|
620
707
|
json.set! :names, names
|
621
708
|
end
|
622
709
|
|
623
710
|
assert_equal %w[firstName lastName], result['names'][0].keys
|
624
711
|
end
|
625
712
|
|
626
|
-
test 'key_format! with
|
713
|
+
test 'deep key_format! with set! extracting hash from object' do
|
714
|
+
comment = Struct.new(:author).new({ first_name: 'camel', last_name: 'case' })
|
715
|
+
result = jbuild do |json|
|
716
|
+
json.key_format! camelize: :lower
|
717
|
+
json.deep_format_keys!
|
718
|
+
json.set! :comment, comment, :author
|
719
|
+
end
|
720
|
+
|
721
|
+
assert_equal %w[firstName lastName], result['comment']['author'].keys
|
722
|
+
end
|
723
|
+
|
724
|
+
test 'deep key_format! with array! of hashes' do
|
627
725
|
names = [{ first_name: 'camel', last_name: 'case' }]
|
628
726
|
result = jbuild do |json|
|
629
727
|
json.key_format! camelize: :lower
|
728
|
+
json.deep_format_keys!
|
630
729
|
json.array! names
|
631
730
|
end
|
632
731
|
|
633
732
|
assert_equal %w[firstName lastName], result[0].keys
|
634
733
|
end
|
635
734
|
|
636
|
-
test 'key_format! with merge! array of hashes' do
|
735
|
+
test 'deep key_format! with merge! array of hashes' do
|
637
736
|
names = [{ first_name: 'camel', last_name: 'case' }]
|
638
737
|
new_names = [{ first_name: 'snake', last_name: 'case' }]
|
639
738
|
result = jbuild do |json|
|
640
739
|
json.key_format! camelize: :lower
|
740
|
+
json.deep_format_keys!
|
641
741
|
json.array! names
|
642
742
|
json.merge! new_names
|
643
743
|
end
|
@@ -645,6 +745,39 @@ class JbuilderTest < ActiveSupport::TestCase
|
|
645
745
|
assert_equal %w[firstName lastName], result[1].keys
|
646
746
|
end
|
647
747
|
|
748
|
+
test 'deep key_format! is applied to hash extracted from object' do
|
749
|
+
comment = Struct.new(:author).new({ first_name: 'camel', last_name: 'case' })
|
750
|
+
result = jbuild do |json|
|
751
|
+
json.key_format! camelize: :lower
|
752
|
+
json.deep_format_keys!
|
753
|
+
json.extract! comment, :author
|
754
|
+
end
|
755
|
+
|
756
|
+
assert_equal %w[firstName lastName], result['author'].keys
|
757
|
+
end
|
758
|
+
|
759
|
+
test 'deep key_format! is applied to hash extracted from hash' do
|
760
|
+
comment = {author: { first_name: 'camel', last_name: 'case' }}
|
761
|
+
result = jbuild do |json|
|
762
|
+
json.key_format! camelize: :lower
|
763
|
+
json.deep_format_keys!
|
764
|
+
json.extract! comment, :author
|
765
|
+
end
|
766
|
+
|
767
|
+
assert_equal %w[firstName lastName], result['author'].keys
|
768
|
+
end
|
769
|
+
|
770
|
+
test 'deep key_format! is applied to hash extracted directly from array' do
|
771
|
+
comments = [Struct.new(:author).new({ first_name: 'camel', last_name: 'case' })]
|
772
|
+
result = jbuild do |json|
|
773
|
+
json.key_format! camelize: :lower
|
774
|
+
json.deep_format_keys!
|
775
|
+
json.array! comments, :author
|
776
|
+
end
|
777
|
+
|
778
|
+
assert_equal %w[firstName lastName], result[0]['author'].keys
|
779
|
+
end
|
780
|
+
|
648
781
|
test 'default key_format!' do
|
649
782
|
Jbuilder.key_format camelize: :lower
|
650
783
|
result = jbuild{ |json| json.camel_style 'for JS' }
|
@@ -47,7 +47,7 @@ if Rails::VERSION::MAJOR > 4
|
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
|
-
test '
|
50
|
+
test "don't use require and permit if there are no attributes" do
|
51
51
|
run_generator %w(Post --api)
|
52
52
|
|
53
53
|
assert_file 'app/controllers/posts_controller.rb' do |content|
|
@@ -31,14 +31,14 @@ class ScaffoldControllerGeneratorTest < Rails::Generators::TestCase
|
|
31
31
|
assert_instance_method :create, content do |m|
|
32
32
|
assert_match %r{@post = Post\.new\(post_params\)}, m
|
33
33
|
assert_match %r{@post\.save}, m
|
34
|
-
assert_match %r{format\.html \{ redirect_to @post, notice: "Post was successfully created\." \}}, m
|
34
|
+
assert_match %r{format\.html \{ redirect_to post_url\(@post\), notice: "Post was successfully created\." \}}, m
|
35
35
|
assert_match %r{format\.json \{ render :show, status: :created, location: @post \}}, m
|
36
36
|
assert_match %r{format\.html \{ render :new, status: :unprocessable_entity \}}, m
|
37
37
|
assert_match %r{format\.json \{ render json: @post\.errors, status: :unprocessable_entity \}}, m
|
38
38
|
end
|
39
39
|
|
40
40
|
assert_instance_method :update, content do |m|
|
41
|
-
assert_match %r{format\.html \{ redirect_to @post, notice: "Post was successfully updated\." \}}, m
|
41
|
+
assert_match %r{format\.html \{ redirect_to post_url\(@post\), notice: "Post was successfully updated\." \}}, m
|
42
42
|
assert_match %r{format\.json \{ render :show, status: :ok, location: @post \}}, m
|
43
43
|
assert_match %r{format\.html \{ render :edit, status: :unprocessable_entity \}}, m
|
44
44
|
assert_match %r{format\.json \{ render json: @post.errors, status: :unprocessable_entity \}}, m
|
@@ -59,7 +59,26 @@ class ScaffoldControllerGeneratorTest < Rails::Generators::TestCase
|
|
59
59
|
end
|
60
60
|
end
|
61
61
|
|
62
|
-
|
62
|
+
if Rails::VERSION::MAJOR >= 6
|
63
|
+
test 'controller with namespace' do
|
64
|
+
run_generator %w(Admin::Post --model-name=Post)
|
65
|
+
assert_file 'app/controllers/admin/posts_controller.rb' do |content|
|
66
|
+
assert_instance_method :create, content do |m|
|
67
|
+
assert_match %r{format\.html \{ redirect_to admin_post_url\(@post\), notice: "Post was successfully created\." \}}, m
|
68
|
+
end
|
69
|
+
|
70
|
+
assert_instance_method :update, content do |m|
|
71
|
+
assert_match %r{format\.html \{ redirect_to admin_post_url\(@post\), notice: "Post was successfully updated\." \}}, m
|
72
|
+
end
|
73
|
+
|
74
|
+
assert_instance_method :destroy, content do |m|
|
75
|
+
assert_match %r{format\.html \{ redirect_to admin_posts_url, notice: "Post was successfully destroyed\." \}}, m
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
test "don't use require and permit if there are no attributes" do
|
63
82
|
run_generator %w(Post)
|
64
83
|
|
65
84
|
assert_file 'app/controllers/posts_controller.rb' do |content|
|
data/test/test_helper.rb
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
require "bundler/setup"
|
2
2
|
|
3
|
-
require "
|
3
|
+
require "rails"
|
4
|
+
|
5
|
+
require "jbuilder"
|
6
|
+
|
4
7
|
require "active_support/core_ext/array/access"
|
5
8
|
require "active_support/cache/memory_store"
|
6
9
|
require "active_support/json"
|
7
10
|
require "active_model"
|
8
|
-
require "action_view"
|
9
|
-
require "rails/version"
|
10
|
-
|
11
|
-
require "jbuilder"
|
12
11
|
|
13
12
|
require "active_support/testing/autorun"
|
14
13
|
require "mocha/minitest"
|
@@ -21,7 +20,13 @@ class << Rails
|
|
21
20
|
end
|
22
21
|
end
|
23
22
|
|
24
|
-
|
23
|
+
Jbuilder::CollectionRenderer.collection_cache = Rails.cache
|
24
|
+
|
25
|
+
class Post < Struct.new(:id, :body, :author_name)
|
26
|
+
def cache_key
|
27
|
+
"post-#{id}"
|
28
|
+
end
|
29
|
+
end
|
25
30
|
|
26
31
|
class Racer < Struct.new(:id, :name)
|
27
32
|
extend ActiveModel::Naming
|
@@ -29,6 +34,3 @@ class Racer < Struct.new(:id, :name)
|
|
29
34
|
end
|
30
35
|
|
31
36
|
ActionView::Template.register_template_handler :jbuilder, JbuilderHandler
|
32
|
-
|
33
|
-
ActionView::Base.remove_possible_method :fragment_name_with_digest
|
34
|
-
ActionView::Base.remove_possible_method :cache_fragment_name
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jbuilder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.11.
|
4
|
+
version: 2.11.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Heinemeier Hansson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-12-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -24,16 +24,29 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 5.0.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: actionview
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 5.0.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 5.0.0
|
27
41
|
description:
|
28
42
|
email: david@basecamp.com
|
29
43
|
executables: []
|
30
44
|
extensions: []
|
31
45
|
extra_rdoc_files: []
|
32
46
|
files:
|
47
|
+
- ".github/workflows/ruby.yml"
|
33
48
|
- ".gitignore"
|
34
|
-
- ".travis.yml"
|
35
49
|
- Appraisals
|
36
|
-
- CHANGELOG.md
|
37
50
|
- CONTRIBUTING.md
|
38
51
|
- Gemfile
|
39
52
|
- MIT-LICENSE
|
@@ -43,6 +56,7 @@ files:
|
|
43
56
|
- gemfiles/rails_5_1.gemfile
|
44
57
|
- gemfiles/rails_5_2.gemfile
|
45
58
|
- gemfiles/rails_6_0.gemfile
|
59
|
+
- gemfiles/rails_6_1.gemfile
|
46
60
|
- gemfiles/rails_head.gemfile
|
47
61
|
- jbuilder.gemspec
|
48
62
|
- lib/generators/rails/jbuilder_generator.rb
|
@@ -54,6 +68,7 @@ files:
|
|
54
68
|
- lib/generators/rails/templates/show.json.jbuilder
|
55
69
|
- lib/jbuilder.rb
|
56
70
|
- lib/jbuilder/blank.rb
|
71
|
+
- lib/jbuilder/collection_renderer.rb
|
57
72
|
- lib/jbuilder/dependency_tracker.rb
|
58
73
|
- lib/jbuilder/errors.rb
|
59
74
|
- lib/jbuilder/jbuilder.rb
|
@@ -70,7 +85,12 @@ files:
|
|
70
85
|
homepage: https://github.com/rails/jbuilder
|
71
86
|
licenses:
|
72
87
|
- MIT
|
73
|
-
metadata:
|
88
|
+
metadata:
|
89
|
+
bug_tracker_uri: https://github.com/rails/jbuilder/issues
|
90
|
+
changelog_uri: https://github.com/rails/jbuilder/releases/tag/v2.11.5
|
91
|
+
mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
|
92
|
+
source_code_uri: https://github.com/rails/jbuilder/tree/v2.11.5
|
93
|
+
rubygems_mfa_required: 'true'
|
74
94
|
post_install_message:
|
75
95
|
rdoc_options: []
|
76
96
|
require_paths:
|
@@ -86,7 +106,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
86
106
|
- !ruby/object:Gem::Version
|
87
107
|
version: '0'
|
88
108
|
requirements: []
|
89
|
-
rubygems_version: 3.
|
109
|
+
rubygems_version: 3.2.32
|
90
110
|
signing_key:
|
91
111
|
specification_version: 4
|
92
112
|
summary: Create JSON structures via a Builder-style DSL
|