Deep nested Hash defaults in presenter default cannot render
Consider:
class TestHashKeyDeepDefaultAggregation < Hoodoo::Presenters::Base
schema do
hash :test do # A default here would implicitly override anything on :two below
key :one, :default => { :foo => 'bar' }
key :three, :type => :integer
key :two do
hash :inner_two, :default => { 'inner_three' => 'three' } do
key :inner_one, :default => { :bar => 'baz' }
key :inner_three, :type => :text
end
end
end
end
end
...this might seem reasonable:
it 'aggregates default deep Hash and key values' do
expected = {
'test' => {
'one' => { 'foo' => 'bar' },
'two' => {
'inner_two' => {
'inner_one' => { 'bar' => 'baz' },
'inner_three' => 'three'
}
}
}
}
expect( TestHashKeyDeepDefaultAggregation.render( {} ) ).to eql( expected )
end
...but the presenter engine cannot "see" the Hash default on key :two, because the embedded block runs in a context that's not aware of its parent and thus when the rendering code is stepping through the parent Hash's properties, it sees no data for :two and no default on that specific property, even though there's a "hidden"/unnoticed default sitting inside which logically a coder might assume would work: https://github.com/LoyaltyNZ/hoodoo/blob/master/lib/hoodoo/presenters/types/hash.rb#L300 (there is no key in the inbound data but the local property has no defaults either, so the loop hits the next condition and does not render anything).
This is an arguable limitation of the DSL but could be considered a bug, so it should either be documented or somehow fixed (the mess of trying to have children address their parent's default properties is probably too nasty to contemplate and pushes us towards The Rewrite Mistake on the presentation and validation engine).
A work-around is to put a nested Hash default up a level, onto the key, but this is not obvious and inelegant as one must then remember to include the inner Hash's name as a key in the outermost part of the default thus:
key :two, :default => { 'inner_two' => { 'inner_three' => 'three' } } do
hash :inner_two do