0.0
Repository is archived
No release in over 3 years
Low commit activity in last 3 years
Stores a model attributes in a time period
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

~> 1.17
>= 4.0, < 6.1
~> 1.2.3
>= 0.3, < 1
~> 13.0
~> 3.0
>= 0.3, < 1

Runtime

>= 4.1, < 6.2
>= 4.1, < 6.2
>= 1, < 2
 Project Readme

Build Status Maintainability

Snapshotable

This gem is intended to work as a model history, saving important information about it (and its relations) over time.

Installation

Add this line to your application's Gemfile:

gem 'snapshotable'

And then execute:

$ bundle

Or install it yourself as:

$ gem install snapshotable

Setup

Creating the model and migration

We provide a helpful generator to create migrations and models easily. Simply run:

rails generate snapshotable:create <model_to_be_snapshoted>

Example:

rails generate snapshotable:create user

This would create a create_user_snapshot migration

class CreateContractSnapshots < ActiveRecord::Migration
  def change
    create_table :user_snapshots do |t|
      # model to be snapshoted
      t.references :user, index: true, null: false, foreign_key: true

      # snapshoted_object
      t.jsonb :object, null: false
      t.timestamps null: false
    end
  end
end

and a UserSnapshot model

class UserSnapshot < ApplicationRecord
  belongs_to :user

  validates :user, presence: true
  validates :object, presence: true
end

Saving relation information

It's possible to add --has_one or --has_many options to the generator, which creates the needed attributes

Example:

rails generate snapshotable:create user --has_one profile photo --has_many groups friends 

This would create a create_user_snapshot migration

class CreateContractSnapshots < ActiveRecord::Migration
  def change
    create_table :user_snapshots do |t|
      # model to be snapshoted
      t.references :user, index: true, null: false, foreign_key: true

      # snapshoted_attributes
      t.jsonb :object, null: false
      
      t.jsonb :profile_object, null: false
      t.jsonb :photo_object, null: false

      t.jsonb :groups_object, null: false, array: true, default: []
      t.jsonb :friends_object, null: false, array: true, default: []

      t.timestamps null: false
    end
  end
end

In this case, the model won't change, but you could modify it manually if you wish.

Setting the base model

Set which attributes should be saved on the Snapshot using snapshot on the model

snapshot :id, :name, :age, profile: [:description], photo: [:url], groups: [:name], friends: [:name, :age]

Creating a Snapshot

Run take_snapshot! to save a new snapshot from a model instance. This will only save a new snapshot if any of the saved fields have changed.

In the example above a UserSnapshot would be created like this:

{
  user_id: user.id,
  object: {
    id: user.id,
    name: user.name,
    age: user.age
  },
  profile_object: {
    description: user.profile.description
  },
  photo_object: {
    url: user.photo.url
  },
  groups_object: [{
    name: user.groups.first.name
  },
  {
    name: user.groups.second.name
  }],
  friends_object: [{
    name: user.friends.first.name,
    age: user.friends.first.age
  },
  {
    name: user.friends.second.name,
    age: user.friends.second.age
  }]
}

License

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