Giter Club home page Giter Club logo

activerecord-typedstore's Introduction

ActiveRecord::TypedStore

Gem Version

ActiveRecord::Store but with typed attributes.

Installation

Add this line to your application's Gemfile:

gem 'activerecord-typedstore'

And then execute:

$ bundle

Or install it yourself as:

$ gem install activerecord-typedstore

Usage

It 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 attributes
shop = Shop.new(email: '[email protected]')
shop.public?        # => false
shop.email          # => '[email protected]'
shop.published_at   # => nil

# Values are type casted
shop.update_attributes(
  age: '42',
  published_at: '1984-06-08 13:57:12'
)
shop.age                # => 42
shop.published_at.class #= DateTime

# And changes are tracked
shop.age_changed? # => false
shop.age = 12
shop.age_changed? # => true
shop.age_was      # => 42

# You can still use it as a regular store
shop.settings[:unknown] = 'Hello World'
shop.save
shop.reload
shop.settings[:unknown] # => 'Hello World'

# You can group attributes with a prefix or suffix
typed_store(:browser, prefix: true) { |s| s.string :ip } # => #browser_ip
typed_store(:browser, prefix: :web) { |s| s.string :ip } # => #web_ip
typed_store(:browser, suffix: true) { |s| s.string :ip } # => #ip_browser
typed_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 wide
typed_store :settings, accessors: false do |s|
  # ...
end

# or on a per attribute basis
typed_store :settings do |s|
  s.integer :age
  s.string :postal_code, accessor: false
end

Type 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

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|
  # ...
end

If you want to use JSON column or Postgres HStore types, then you can pass in ActiveRecord::TypedStore::IdentityCoder as the coder.

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:

  • array attributes won't work
  • any attributes 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

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request

activerecord-typedstore's People

Contributors

byroot avatar rafaelfranca avatar kirs avatar arthurnn avatar edouard-chin avatar sgrif avatar casperisfine avatar adis-io avatar adrianna-chang-shopify avatar dannytip avatar kmcphillips avatar dwightwatson avatar etiennebarrie avatar dimitris-personal avatar taykangsheng avatar petergoldstein avatar olleolleolle avatar joshk avatar jonathanhefner avatar dwillett avatar cjoudrey avatar bdewater avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.