1
0
mirror of https://github.com/jbranchaud/til synced 2026-01-02 22:58:01 +00:00

Add Convert JSON Field To Hash With Indifferent Access as a Rails TIL

This commit is contained in:
jbranchaud
2025-11-08 08:55:41 -05:00
parent 9e76753540
commit 16074c021f
2 changed files with 38 additions and 1 deletions

View File

@@ -10,7 +10,7 @@ pairing with smart people at Hashrocket.
For a steady stream of TILs, [sign up for my newsletter](https://crafty-builder-6996.ck.page/e169c61186).
_1680 TILs and counting..._
_1681 TILs and counting..._
See some of the other learning resources I work on:
@@ -1051,6 +1051,7 @@ If you've learned something here, support my efforts writing daily TILs by
- [Comparing DateTimes Down To Second Precision](rails/comparing-datetimes-down-to-second-precision.md)
- [Conditional Class Selectors in Haml](rails/conditional-class-selectors-in-haml.md)
- [Convert A Symbol To A Constant](rails/convert-a-symbol-to-a-constant.md)
- [Convert JSON Field To Hash With Indifferent Access](rails/convert-json-field-to-hash-with-indifferent-access.md)
- [Count The Number Of Records By Attribute](rails/count-the-number-of-records-by-attribute.md)
- [Create A Custom Named References Column](rails/create-a-custom-named-references-column.md)
- [Create A Join Table With The Migration DSL](rails/create-a-join-table-with-the-migration-dsl.md)

View File

@@ -0,0 +1,36 @@
# Convert JSON Field To Hash With Indifferent Access
Let's say we have an `Event` model whose backing table includes a `JSONB` (or
`JSON`) field called `details`.
When we access `details` in a Rails context, digging into that nested data we
have to use string keys throughout. However, we may have existing related code
that is dealing with this shape of data using symbol keys. This might put us in
a position where we have to rework a bunch of existing code or do defensive
coding like `details[:user] || details["user"]`.
To avoid that, we can instead have the `Event` model override `details`
converting that underlying data to `HashWithIndifferentAccess` before returning
it.
```ruby
class Event < ApplicationRecord
def details
data = super
return data if data.nil?
case data
when Array
data.map { |item| item.is_a?(Hash) ? item.with_indifferent_access : item }
when Hash
data.with_indifferent_access
else
data
end
end
end
```
With this in place, anywhere in the codebase where we access `details` on an
instance of `Event` we will be able to use string or symbol keys
interchangeably.