The project is in a healthy, maintained state
Typed store for active records json/hstore columns
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies
 Project Readme

ActiveTypedStore

active_typed_store is a lightweight (65 lines of code) and highly performant gem (see benchmarks) designed to help you store and manage typed data in JSON format within database. This gem provides a simple, yet powerful way to ensure that your JSON data cast to specific types, enabling more structured and reliable use of JSON fields in your Rails models.

You can use ActiveRecord Types for simplicity or Dry Types for more advanced features such as constraints and type composition. You can also combine both approaches in the same model to get the best of both worlds.

Installation

Add this line to your application's Gemfile:

gem "active_typed_store"

Usage

class Model < ActiveRecord::Base
  typed_store(:params) do # params - the name of the store
    attr :task_id,   :integer
    attr :name,      :string
    attr :notify_at, :datetime
    attr :asap,      :boolean, default: false
    attr :settings,  :json
  end
end

m = Model.first
m.task_id = "123" # string
m.task_id # => 123, int
m.task_id? # => true, value.present? under the hood
m.asap? # => false
m.asap = "yes"
m.asap # => true
m.asap? # => true

attr(name, type, options)

  • name the name of the accessor to the store
  • type a symbol such as :string or :integer, or a type object to be used for the accessor
  • options (optional), a hash of cast type options such as:
    • precision, limit, scale
    • default the default value to use when no value is provided. Otherwise, the default will be nil
    • array specifies that the type should be an array

Using Dry Types

class Model < ActiveRecord::Base
  typed_store(:params) do
    attr :task_id,   Types::Params::Integer
    attr :name,      Types::Params::String
    attr :notify_at, Types::Params::Time
    attr :asap,      Types::Params::Bool.default(false)
    attr :email,     Types::String.constrained(format: /@/)
    attr :settings,  Types::Params::Hash
  end
end

Combine ActiveRecord and Dry Types

class Model < ActiveRecord::Base
  typed_store(:params) do
    attr :price,  :decimal, scale: 2
    attr :active, :immutable_string
    attr :email,  Types::String.constrained(format: /@/)
    attr :state,  Types::String.enum('draft', 'published', 'archived')
    attr :tariff_id, Types::Array.of(Types::Params::Integer)
  end
end

Benchmarks

compare active_typed_store with other gems

#                    gem     getter  i/s                setter i/s            Lines of code
#  rails (without types):    27930.8                    660                   170
#     active_typed_store:    24318.5 - 1.15x  slower    656                   65
#        store_attribute:    23748.3 - 1.18x  slower    639                   276
#            store_model:    23324.4 - 1.20x  slower    595                   857
#              attr_json:    15541.4 - 1.80x  slower    577 - 1.14x  slower   1195
#         jsonb_accessor:    15000.1 - 1.86x  slower    626                   324

License

The gem is available as open source under the terms of the MIT License.