module Sequel::Plugins::Revisions

Public Class Methods

apply(model, options = {}) click to toggle source
# File lib/sequel/plugins/revisions.rb, line 7
def self.apply(model, options = {})
  options = set_options(model, options)
  model.class_eval do
    @revisions_polymorphic = options[:polymorphic]
    @revisions_embedded_in = options[:embedded_in]
    @revisions_on          = options[:on]
    @revisions_meta        = options[:meta]
    @revisions_exclude     = options[:exclude]
  end
end
configure(model, options = {}) click to toggle source
# File lib/sequel/plugins/revisions.rb, line 18
def self.configure(model, options = {})
  options = set_options(model, options)

  base_name = options[:model_name]

  mods = options[:model_name].split("::")
  if mods.length > 1
    mobject = Object.const_get mods[0..mods.length-2].join("::")
    base_name = mods.last
  else
    mobject = Object
  end

  # Don't redefine and don't define for embedded revisions
  if !mobject.const_defined?(base_name) && options[:embedded_in].nil?
    klass = setup_revisions_model(model, options)
    # Actually define the class in the module
    mobject.const_set base_name, klass
  end

  # Configure associations / methods on models
  setup_model(model, options)
end

Private Class Methods

set_options(model, options) click to toggle source
# File lib/sequel/plugins/revisions.rb, line 130
def self.set_options(model, options)
  model_name = options[:polymorphic] ? "Revision" : "#{model.name}Revision"
  table_name = options[:polymorphic] ? "revisions" : "#{model.table_name.to_s.singularize}_revisions"

  options = {
    model_name: model_name,
    table_name: table_name,
    exclude: [:id, :created_at, :updated_at],
    meta: nil
  }.merge(options)
end
setup_model(model, options) click to toggle source
# File lib/sequel/plugins/revisions.rb, line 168
def self.setup_model(model, options)
  model.class_eval do
    plugin :dirty

    def revert
      return if revisions.empty?

      last = revisions.last
      changes = last.changes
      changes.keys.each do |key|
        send("#{key}=", changes[key][0])
      end
    end

    def revert!
      revert
      save
    end
  end

  if options[:polymorphic]
    model.class_eval do
      one_to_many :revisions, as: :trackable, class: "::#{options[:model_name]}"
    end
  elsif options[:embedded_in]
    model.class_eval do
      one_to_many :revisions, as: :embeddable, class: "::#{options[:model_name]}"
    end
  else
    model.class_eval do
      one_to_many :revisions, class: "::#{options[:model_name]}"
    end
  end
end
setup_revisions_model(model, options) click to toggle source
# File lib/sequel/plugins/revisions.rb, line 142
def self.setup_revisions_model(model, options)
  # Dynamically create Model class
  klass = Class.new(Sequel::Model(options[:table_name].to_sym))
  klass.class_eval do
    plugin :timestamps
    plugin :serialization

    serialize_attributes :json, :meta
    serialize_attributes :json, :changes
  end

  if options[:polymorphic]
    klass.class_eval do
      plugin :polymorphic
      many_to_one :trackable, polymorphic: true
      many_to_one :embeddable, polymorphic: true
    end
  else
    klass.class_eval do
      many_to_one model.table_name.to_sym, class: model.name
    end
  end

  klass
end

Private Instance Methods

revert() click to toggle source
# File lib/sequel/plugins/revisions.rb, line 172
def revert
  return if revisions.empty?

  last = revisions.last
  changes = last.changes
  changes.keys.each do |key|
    send("#{key}=", changes[key][0])
  end
end
revert!() click to toggle source
# File lib/sequel/plugins/revisions.rb, line 182
def revert!
  revert
  save
end