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 HashWithIndifferentAccess
is great, but it still acts like a Hash, and it can only serialize as YAML in the database.
My preference, using Postgres 9.3 and higher, is to use the json column type in Postgres. This means that when the table is read, ActiveRecord will get a Hash directly from Postgres.
create_table "gadgets" do |t|
t.json "info"
end
ActiveRecord serialize
requires that you provide it a single class that is both responsible for reading/writing the data and serializing/deserializing it.
So you can create an object that does the job by inheriting from HashWithIndifferentAccess
, or my preference, Hashie::Mash
. Then you implement the serialization as the dump
and load
class methods.
class HashieMashStoredAsJson < Hashie::Mash
def self.dump(obj)
ActiveSupport::JSON.encode(obj.to_h)
end
def self.load(raw_hash)
new(raw_hash || {})
end
end
In your model, you can specify this class for serialization.
class Gadget < ActiveRecord::Base
serialize :info, HashieMashStoredAsJson
# This allows the field to be set as a Hash or anything compatible with it.
def info=(new_value)
self[:info] = HashieMashStoredAsJson.new new_value
end
end
If you don't use the json column type in Postgres, the implementation changes slightly
Full code and documentation here: using a JSON column type and using a string column type.