byroot/activerecord-typedstore
{ "createdAt": "2013-10-26T22:04:54Z", "defaultBranch": "master", "description": "ActiveRecord::Store but with type definition", "fullName": "byroot/activerecord-typedstore", "homepage": null, "language": "Ruby", "name": "activerecord-typedstore", "pushedAt": "2024-02-28T09:58:15Z", "stargazersCount": 464, "topics": [], "updatedAt": "2025-11-01T23:08:02Z", "url": "https://github.com/byroot/activerecord-typedstore"}ActiveRecord::TypedStore
Section titled “ActiveRecord::TypedStore”ActiveRecord::Store but with typed attributes.
Installation
Section titled “Installation”Add this line to your application’s Gemfile:
gem 'activerecord-typedstore'And then execute:
$ bundleOr install it yourself as:
$ gem install activerecord-typedstoreIt works exactly like ActiveRecord::Store documentation but you can declare the type of your attributes.
Attributes definition is similar to activerecord’s migrations:
class Shop < ActiveRecord::Base
typed_store :settings do |s| s.boolean :public, default: false, null: false s.string :email s.datetime :publish_at s.integer :age, null: false
# You can define array attributes like in rails 4 and postgres s.string :tags, array: true, default: [], null: false
# In addition to prevent null values you can prevent blank values s.string :title, blank: false, default: 'Title'
# If you don't want to enforce a datatype but still like to have default handling s.any :source, blank: false, default: 'web' end
# You can use any ActiveModel validator validates :age, presence: true
end
# Values are accessible like normal model attributesshop = Shop.new(email: 'george@cyclim.se')shop.public? # => falseshop.email # => 'george@cyclim.se'shop.published_at # => nil
# Values are type castedshop.update_attributes( age: '42', published_at: '1984-06-08 13:57:12')shop.age # => 42shop.published_at.class #= DateTime
# And changes are trackedshop.age_changed? # => falseshop.age = 12shop.age_changed? # => trueshop.age_was # => 42
# You can still use it as a regular storeshop.settings[:unknown] = 'Hello World'shop.saveshop.reloadshop.settings[:unknown] # => 'Hello World'
# You can group attributes with a prefix or suffixtyped_store(:browser, prefix: true) { |s| s.string :ip } # => #browser_iptyped_store(:browser, prefix: :web) { |s| s.string :ip } # => #web_iptyped_store(:browser, suffix: true) { |s| s.string :ip } # => #ip_browsertyped_store(:browser, suffix: :web) { |s| s.string :ip } # => #ip_web
# If you only want type casting and default handling without accessors
# you can disable them store widetyped_store :settings, accessors: false do |s| # ...end
# or on a per attribute basistyped_store :settings do |s| s.integer :age s.string :postal_code, accessor: falseendType casting rules and attribute behavior are exactly the same as for real database columns. Actually the only difference is that you won’t be able to query on these attributes (unless you use JSON or Postgres HStore types) and that you don’t need to do a migration to add / remove an attribute.
If not, then please fill in an issue.
Serialization methods
Section titled “Serialization methods”Just like for store, you can use any custom coder:
module Base64MarshalCoder extend self
def load(data) return {} unless data Marshal.load(Base64.decode64(data)) end
def dump(data) Base64.encode64(Marshal.dump(data || {})) end
end
typed_store :settings, coder: Base64MarshalCoder do |s| # ...endIf you want to use JSON column or Postgres HStore types, then you can pass in ActiveRecord::TypedStore::IdentityCoder as the coder.
HStore limitations
Section titled “HStore limitations”If you want to persist your store in a Postgres HStore, then there is some limitations imposed by the current HStore implementation in Postgres. Since HStore can only store strings:
arrayattributes won’t workanyattributes will be converted to string
If you use HStore because you need to be able to query the store from SQL, and any of these limitations are an issue for you, then you could probably use the JSON column type, which do not suffer from these limitations and is also queriable.
Contributing
Section titled “Contributing”- Fork it
- Create your feature branch (
git checkout -b my-new-feature) - Commit your changes (
git commit -am 'Add some feature') - Push to the branch (
git push origin my-new-feature) - Create new Pull Request