3.6.0 Hashie::Mash#merge doesn't work for instances with default_proc that raise error
andrew-hai opened this issue · 13 comments
2.5.1 :001 > require 'hashie'
=> true
2.5.1 :002 > mash = Hashie::Mash.new(foo: 1) { |hash, key| raise StandardError, "Key #{key} does not exist in hash #{hash.inspect}" }
=> #<Hashie::Mash foo=1>
2.5.1 :003 > mash.merge(bar: 2)
Traceback (most recent call last):
8: from /home/an/.rvm/rubies/ruby-2.5.1/bin/irb:11:in `<main>'
7: from (irb):3
6: from /home/an/.rvm/gems/ruby-2.5.1@test/gems/hashie-3.6.0/lib/hashie/mash.rb:203:in `deep_merge'
5: from /home/an/.rvm/gems/ruby-2.5.1@test/gems/hashie-3.6.0/lib/hashie/mash.rb:210:in `deep_update'
4: from /home/an/.rvm/gems/ruby-2.5.1@test/gems/hashie-3.6.0/lib/hashie/mash.rb:210:in `each_pair'
3: from /home/an/.rvm/gems/ruby-2.5.1@test/gems/hashie-3.6.0/lib/hashie/mash.rb:212:in `block in deep_update'
2: from /home/an/.rvm/gems/ruby-2.5.1@test/gems/hashie-3.6.0/lib/hashie/mash.rb:212:in `[]'
1: from (irb):2:in `block in irb_binding'
StandardError (Key bar does not exist in hash #<Hashie::Mash foo=1>)
2.5.1 :004 >
Thanks for filing this issue. What do you believe the behavior should be here? Could you please submit a test?
I agree with @michaelherold what is your expectation here? Isn't the above the correct behaviour? An exception should be raised since you defined it no?
I think it's not the expected behavior because assignment and merge
should behave the same way.
2.5.1 :002 > mash = Hashie::Mash.new(foo: 1) { |hash, key| raise StandardError, "Key #{key} does not exist in hash #{hash.inspect}" }
=> #<Hashie::Mash foo=1>
2.5.1 :003 > mash[:bar] = 2
=> 2
Merge doesn't imply needing to check on whether the value exists.
Hi @dblock.
On the default block we override the default value for the getter. Thus any non defined member will raise an exception. Calling mash[:bar] = 2
we send a different message to the object and we override the default value by creating the corresponding member.
So I think that merge
is behaving as expected not because of merge
method's definition but rather by the intention of the code written.
Color me confused, why does merge
call any getters?
Hi,
As for me, I expect the same behavior as for Hash#merge
with the same default_proc
. Also it works for previous versions. I think it because of changing alias_method
definitions to alias
.
@dblock You are right. It has nothing to do with merge...
@andrew-hai Care to try to write a spec and, hopefully, a fix?
This introduced the problematic change: https://github.com/intridea/hashie/pull/435/files. The problem is that calling regular_reader
(Hash#[]) or custom_reader
will execute the default block that is passed.
I've made a super small change in a related PR where we check the key before calling any getter on the Mash.
@laertispappas and all others, thank you, Hashie::Mash#merge
method works fine now.
Do I presume correctly that this will appear in v3.6.1? Any ETA on v3.6.1? (Not pushing; really just wondering if there are any major blockages preventing its tagging/release.)
No ETA, sorry. My charity says I could make a release with some convincing.