/ rails_3

Rails Store - A solution to store multiple value in single column.

What is ActiveRecord::Store?

  1. Store provides a simple means of accessing and storing key/value pairs related to a model.

  2. Store gives you a thin wrapper around serialize for the purpose of storing hashes in a single column.

In simple words, it is used for storing mutiple columns under a single column. Its serailized/deserialized to save and load the data for easy access.

Example

You have a Music application, you want to cache the last volume adjustment for the user. So that when he returns back, same volume level is applied, similarly other volume related settings. Now you can save the multiple settings in one column.

audio_settings => {volume: 70, equaliser: true, equaliser_option: "rock"}

here, audio_settings is the store.

How it works?

  1. You can then declare accessors to the store(audio_settings) that are then accessible just like any other attribute of the model.

  2. Instead of accessing the attributes through audio_settings as you would a normal Hash, you access them as if they were attributes on the model itself. For example: User.find(1).volume #=> 70.

  3. Store fields are just hashes. This means you can access them and use methods on them just like any other hash.

    a. You can even add attributes not defined in the store.

    b. Store values of different data-types.

  4. You can also add validations to the accessors of store, like volume cant be greater than 100 or less than 0.

    validates :volume, numericality: { only_integer: true,
    greater_than: 0,
    less_than_or_equal_to: 100 }

When to use?

It can only be used at an instance level, not at class level. If you believe you would intend to use at class level, like User.where(equaliser: true), you would be better having a one extra column for equaliser.

How to setup?

  1. Make sure that you declare the database column used for the serialized store as a text, so there’s plenty of room.

    class CreateUsers < ActiveRecord::Migration
    def change
    create_table :users do |t|
    t.text :audio_settings
    t.timestamps
    end
    end
    end

  2. Next, we’ll need to let the user model know we’ll be using the audio_settings field as a store.

    class User < ActiveRecord::Base
    store :audio_settings, accessors: [ :volume, :equaliser, :equaliser_option ]
    end

  3. Besides one can set custom coder to encode/decode your serialized attributes to/from different formats. JSON, YAML, Marshal are supported out of the box. Generally it can be any wrapper that provides load and dump.

Advantage:

No extra table or extra columns. Works as a normal attribute of a model, validation works.

Cons:

Search wont be optimized, cant be used as a global scope solutions.