From 2543bf2fc2d1a89f12f696119722f6bab2a41bdf Mon Sep 17 00:00:00 2001 From: Rafael Bacchi Date: Wed, 27 Sep 2017 17:43:57 +0200 Subject: [PATCH 1/2] Make json.extract! accept objects with internal hash implementation --- lib/jbuilder.rb | 14 ++++---------- test/jbuilder_test.rb | 22 ++++++++++++++++++++++ 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/lib/jbuilder.rb b/lib/jbuilder.rb index d84eab21..18b061fc 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 ae15c042..4e30a05a 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 From 4c3d6f397983dc9ffa158fe19335ae65786855b8 Mon Sep 17 00:00:00 2001 From: Rafael Bacchi Date: Sun, 2 Dec 2018 14:06:59 +0100 Subject: [PATCH 2/2] Fix json.extract! to use first the hash implementation and public_send as fallback --- lib/jbuilder.rb | 2 +- test/jbuilder_test.rb | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/jbuilder.rb b/lib/jbuilder.rb index 18b061fc..c41ebb14 100644 --- a/lib/jbuilder.rb +++ b/lib/jbuilder.rb @@ -251,7 +251,7 @@ def target! private def _extract_value(object, attribute) - object.respond_to?(attribute) ? object.public_send(attribute) : object.fetch(attribute) + object.respond_to?(:[]) ? object[attribute] : object.public_send(attribute) end def _merge_block(key) diff --git a/test/jbuilder_test.rb b/test/jbuilder_test.rb index 4e30a05a..9ec11764 100644 --- a/test/jbuilder_test.rb +++ b/test/jbuilder_test.rb @@ -36,11 +36,8 @@ def initialize(name, age) end class PersonWithHash - attr_reader :name, :collection - - def initialize(name, age) - @collection = { age: age } - @name = name + def initialize(name, age, object_id) + @collection = { name: name, age: age, object_id: object_id } end delegate :[], :fetch, to: :@collection @@ -133,14 +130,17 @@ class JbuilderTest < ActiveSupport::TestCase end test 'extracting from object with internal hash' do - person = PersonWithHash.new('David', 32) + person = PersonWithHash.new('David', 32, 1) + ruby_object_id = person.object_id result = jbuild do |json| - json.extract! person, :name, :age + json.extract! person, :name, :age, :object_id end assert_equal 'David', result['name'] assert_equal 32, result['age'] + assert_equal 1, result['object_id'] + assert_not_equal ruby_object_id, result['object_id'] end test 'nesting single child with block' do