TypedHash inherits from HashWithIndifferentAccess, a while ago many methods like .except()would return a true HashWithIndifferentAccess, but recently they changed to return an instance of the same class than the initial hash.
The problem with this is that TypedHash can contain default values for keys, so if you clear a a key with a default, it will be reset on the new instance, which makes for confusing defaults.
Coverage increased (+0.01%) to 94.927% when pulling 1711765a2586362a37640d2c3b25600878fbb883 on typed-hash-slice-and-except into 0f47084d6a0e0e142f6c5d26d53a87ae924751d1 on master.
Coverage increased (+0.01%) to 94.927% when pulling 1711765a2586362a37640d2c3b25600878fbb883 on typed-hash-slice-and-except into 0f47084d6a0e0e142f6c5d26d53a87ae924751d1 on master.
Context
TypedHash
inherits fromHashWithIndifferentAccess
, a while ago many methods like.except()
would return a trueHashWithIndifferentAccess
, but recently they changed to return an instance of the same class than the initial hash.First
slice
in 2017 https://github.com/rails/rails/commit/d6f3b91aaa4af88eda2344629afed64640d51e0f and more recentlyexcept
in 2019: https://github.com/rails/rails/commit/a805d72e901f81f5b043dfd9904b80ce93ebfc01#diff-9f4b3d7342097a6f22290f147a09b77bThe problem with this is that
TypedHash
can contain default values for keys, so if you clear a a key with a default, it will be reset on the new instance, which makes for confusing defaults.e.g.:
{age: 42}.except(:age) => {age: 0}
while you'd likely expect{}
.Solution
We first cast to
HashWIthIndifferentAccess
before calling these methods.@rafaelfranca thoughts?