Skip to content

Commit 5c82764

Browse files
authored
Fix for key_format! when using nested hashes (#486)
Converts the keys of all hashes within arrays and ones being merged in to follow the specified key format. Fixes #473
1 parent 53b386b commit 5c82764

File tree

2 files changed

+67
-5
lines changed

2 files changed

+67
-5
lines changed

lib/jbuilder.rb

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,11 @@ def set!(key, value = BLANK, *args, &block)
4343
# json.age 32
4444
# json.person another_jbuilder
4545
# { "age": 32, "person": { ... }
46-
value.attributes!
46+
_format_keys(value.attributes!)
4747
else
4848
# json.age 32
4949
# { "age": 32 }
50-
value
50+
_format_keys(value)
5151
end
5252
elsif _is_collection?(value)
5353
# json.comments @post.comments, :content, :created_at
@@ -272,11 +272,11 @@ def _merge_values(current_value, updates)
272272
if _blank?(updates)
273273
current_value
274274
elsif _blank?(current_value) || updates.nil? || current_value.empty? && ::Array === updates
275-
updates
275+
_format_keys(updates)
276276
elsif ::Array === current_value && ::Array === updates
277-
current_value + updates
277+
current_value + _format_keys(updates)
278278
elsif ::Hash === current_value && ::Hash === updates
279-
current_value.deep_merge(updates)
279+
current_value.deep_merge(_format_keys(updates))
280280
else
281281
raise MergeError.build(current_value, updates)
282282
end
@@ -286,6 +286,16 @@ def _key(key)
286286
@key_formatter ? @key_formatter.format(key) : key.to_s
287287
end
288288

289+
def _format_keys(hash_or_array)
290+
if ::Array === hash_or_array
291+
hash_or_array.map { |value| _format_keys(value) }
292+
elsif ::Hash === hash_or_array
293+
::Hash[hash_or_array.collect { |k, v| [_key(k), _format_keys(v)] }]
294+
else
295+
hash_or_array
296+
end
297+
end
298+
289299
def _set_value(key, value)
290300
raise NullError.build(key) if @attributes.nil?
291301
raise ArrayError.build(key) if ::Array === @attributes

test/jbuilder_test.rb

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,58 @@ class JbuilderTest < ActiveSupport::TestCase
581581
assert_equal ['oats and friends'], result.keys
582582
end
583583

584+
test 'key_format! with merge!' do
585+
hash = { camel_style: 'for JS' }
586+
result = jbuild do |json|
587+
json.key_format! camelize: :lower
588+
json.merge! hash
589+
end
590+
591+
assert_equal ['camelStyle'], result.keys
592+
end
593+
594+
test 'key_format! with merge! deep' do
595+
hash = { camel_style: { sub_attr: 'for JS' } }
596+
result = jbuild do |json|
597+
json.key_format! camelize: :lower
598+
json.merge! hash
599+
end
600+
601+
assert_equal ['subAttr'], result['camelStyle'].keys
602+
end
603+
604+
test 'key_format! with set! array of hashes' do
605+
names = [{ first_name: 'camel', last_name: 'case' }]
606+
result = jbuild do |json|
607+
json.key_format! camelize: :lower
608+
json.set! :names, names
609+
end
610+
611+
assert_equal %w[firstName lastName], result['names'][0].keys
612+
end
613+
614+
test 'key_format! with array! of hashes' do
615+
names = [{ first_name: 'camel', last_name: 'case' }]
616+
result = jbuild do |json|
617+
json.key_format! camelize: :lower
618+
json.array! names
619+
end
620+
621+
assert_equal %w[firstName lastName], result[0].keys
622+
end
623+
624+
test 'key_format! with merge! array of hashes' do
625+
names = [{ first_name: 'camel', last_name: 'case' }]
626+
new_names = [{ first_name: 'snake', last_name: 'case' }]
627+
result = jbuild do |json|
628+
json.key_format! camelize: :lower
629+
json.array! names
630+
json.merge! new_names
631+
end
632+
633+
assert_equal %w[firstName lastName], result[1].keys
634+
end
635+
584636
test 'default key_format!' do
585637
Jbuilder.key_format camelize: :lower
586638
result = jbuild{ |json| json.camel_style 'for JS' }

0 commit comments

Comments
 (0)