Rails return JSON serialized attribute with_indifferent_access

前端 未结 4 1443
日久生厌
日久生厌 2021-02-07 05:55

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

4条回答
  •  猫巷女王i
    2021-02-07 06:31

    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.

提交回复
热议问题