Sometimes Inconsistency in Data Makes a Lot of Headache
I want to share a small story from my daily work. It looks simple, but it took me some time to understand what was actually going wrong.
Sometimes everything looks correct in the system. No errors. No crashes. Everything is working fine. But still, the output is different in some cases, and it becomes very confusing.
This is one of those stories.
The problem that looked normal
I was working with a simple data structure in my project. It was a hash that contains translations for different languages.
Something like this:
translations = {
"en" => "Hello",
"de" => "Hallo"
}Then I was accessing it like this:
translations[language_code]
translations[language_code.to_sym]Sometimes both were working fine. Sometimes only one was working.
At first, it looked random.
Everything looks correct… but behavior changes
In some cases, this was working:
translations[:en]
# => "Hello"But in other cases:
translations[:en]
# => nilEven though I was sure the key exists.
So I started checking the data.
The real issue I found
After debugging more, I found something interesting.
The same variable was not always the same type.
Sometimes it was a normal Ruby hash:
translations.class
# => HashAnd sometimes it was:
translations.class
# => ActiveSupport::HashWithIndifferentAccessWhat this means
These two behave differently:
1. Normal Ruby Hash
{ "en" => "Hello" }Here:
translations["en"] # works
translations[:en] # nil2. Indifferent Access Hash (Rails)
In Rails, there is special hash:
ActiveSupport::HashWithIndifferentAccessIt allows both string and symbol keys:
translations["en"] # works
translations[:en] # also worksWhy it was happening
The main problem was not the hash itself.
The problem was:
👉 The hash was changing during the flow
Sometimes it was coming from one place as a Rails indifferent hash
Sometimes it was coming from JSON or external source as normal hash
So the system was not consistent.
Simple diagram of what was happening
Step 1: Rails hash
ActiveSupport::HashWithIndifferentAccess
|
v
Step 2: some transformation (to_h / JSON / merge)
|
v
Step 3: normal Ruby HashSo behavior changed in between.
The fix I used
The easiest fix was to normalize the hash.
I used this:
translations = translations.with_indifferent_accessNow everything works fine:
translations[:en]
translations["en"]Both are safe.
What I learned
The main lesson for me was simple:
It is not enough that data looks correct. We also need to check how data behaves in different steps.
In Ruby and Rails, small transformations can change how data works.
And this can create confusing bugs that are hard to notice.
Final thought
Sometimes bugs are not really bugs in code.
They are bugs in assumptions.
And in my case, the assumption was:
"This hash will always stay the same type"
But it did not.