Rails return JSON serialized attribute with_indifferent_access

ruby, ruby-on-rails

Solution

use the built-in `serialize` method :

class Whatever < ActiveRecord::Base
 serialize :params, HashWithIndifferentAccess
end

see ActiveRecord::Base docs on serialization for more info.

Problem

I previously had: ``` serialize :params, JSON ``` But this would return the JSON and convert hash key symbols to strings. I want to reference the hash using symbols, as is most common when working with hashes. I feed it symbols, Rails returns strings. To avoid this, I created my own getter/setter. The setter is simple enough (JSON encode), the getter is: ``` def params read_attribute(:params) || JSON.parse(read_attribute(:params).to_json).with_indifferent_access end ``` I couldn't reference `params` directly because that would cause a loop, so I'm using `read_attribute`, and now my hash keys can be referenced with symbols or strings. However, this does not update the hash: ``` model.params.merge!(test: 'test') puts model.params # => returns default params without merge ``` Which makes me think the hash is being referenced by copy. My question is twofold. Can I extend active record JSON serialization to return indifferent access hash (or not convert symbols to strings), and still have hash work as above with merge? If not, what can I do to improve my getter so that `model.params.merge!` works? I was hoping for something along the lines of (which works): ``` def params_merge!(hash) write_attribute(:params, read_attribute(:params).merge(hash)) end # usage: model.params_merge!(test: 'test') ``` Better yet, just get Rails to return a hash with indifferent access or not convert my symbols into strings! Appreciate any help.

Original source