diff --git a/lib/jbuilder.rb b/lib/jbuilder.rb index d84eab2..18b061f 100644 --- a/lib/jbuilder.rb +++ b/lib/jbuilder.rb @@ -213,10 +213,8 @@ def array!(collection = [], *attributes) # # json.(@person, :name, :age) def extract!(object, *attributes) - if ::Hash === object - _extract_hash_values(object, attributes) - else - _extract_method_values(object, attributes) + attributes.each do |key| + _set_value key, _extract_value(object, key) end end @@ -252,12 +250,8 @@ def target! private - def _extract_hash_values(object, attributes) - attributes.each{ |key| _set_value key, object.fetch(key) } - end - - def _extract_method_values(object, attributes) - attributes.each{ |key| _set_value key, object.public_send(key) } + def _extract_value(object, attribute) + object.respond_to?(attribute) ? object.public_send(attribute) : object.fetch(attribute) end def _merge_block(key) diff --git a/test/jbuilder_test.rb b/test/jbuilder_test.rb index ae15c04..4e30a05 100644 --- a/test/jbuilder_test.rb +++ b/test/jbuilder_test.rb @@ -35,6 +35,17 @@ def initialize(name, age) end end +class PersonWithHash + attr_reader :name, :collection + + def initialize(name, age) + @collection = { age: age } + @name = name + end + + delegate :[], :fetch, to: :@collection +end + class RelationMock include Enumerable @@ -121,6 +132,17 @@ class JbuilderTest < ActiveSupport::TestCase assert_equal 34, result['age'] end + test 'extracting from object with internal hash' do + person = PersonWithHash.new('David', 32) + + result = jbuild do |json| + json.extract! person, :name, :age + end + + assert_equal 'David', result['name'] + assert_equal 32, result['age'] + end + test 'nesting single child with block' do result = jbuild do |json| json.author do