Sha256: 23329afe0a62ac286a496f6c3104aab3bbe69d68e0d7e32bad6031afbe88f3bf

Contents?: true

Size: 1.96 KB

Versions: 53

Compression:

Stored size: 1.96 KB

Contents

module Ruco
  class History
    attr_accessor :timeout
    attr_reader :stack, :position

    def initialize(options)
      @options = options
      @options[:entries] ||= 100
      @timeout = options.delete(:timeout) || 0

      @stack = [{:mutable => false, :created_at => 0, :type => :initial, :state => @options.delete(:state)}]
      @position = 0
    end

    def state
      @stack[@position][:state]
    end

    def add(state)
      return unless tracked_field_changes?(state)
      remove_undone_states
      unless merge? state
        # can no longer modify previous states
        @stack[@position][:mutable] = false

        state_type = type(state)
        @position += 1
        @stack[@position] = {:mutable => true, :type => state_type, :created_at => Time.now.to_f}
      end
      @stack[@position][:state] = state
      limit_stack
    end

    def undo
      @position = [@position - 1, 0].max
    end

    def redo
      @position = [@position + 1, @stack.size - 1].min
    end

    private
    def type(state)
      @options[:track].each do |field|
        if state[field].is_a?(String) && @stack[@position][:state][field].is_a?(String)
          diff = state[field].length - @stack[@position][:state][field].length
          if diff > 0
            return :insert
          elsif diff < 0
            return :delete
          end
        end
      end
      nil
    end

    def merge?(state)
      top = @stack[@position]
      top[:mutable] &&
        top[:type] == type(state) &&
        top[:created_at]+@timeout > Time.now.to_f
    end

    def remove_undone_states
      @stack.slice!(@position + 1, 9999999)
    end

    def tracked_field_changes?(data)
      @options[:track].any? do |field|
        state[field] != data[field]
      end
    end

    def limit_stack
      return if @options[:entries] == 0
      to_remove = @stack.size - @options[:entries]
      return if to_remove < 1
      @stack.slice!(0, to_remove)
      @position -= to_remove
    end
  end
end

Version data entries

53 entries across 53 versions & 1 rubygems

Version Path
ruco-0.4.0 lib/ruco/history.rb
ruco-0.3.0 lib/ruco/history.rb
ruco-0.2.23 lib/ruco/history.rb
ruco-0.2.22 lib/ruco/history.rb
ruco-0.2.21 lib/ruco/history.rb
ruco-0.2.20 lib/ruco/history.rb
ruco-0.2.19 lib/ruco/history.rb
ruco-0.2.18 lib/ruco/history.rb
ruco-0.2.17 lib/ruco/history.rb
ruco-0.2.16 lib/ruco/history.rb
ruco-0.2.15 lib/ruco/history.rb
ruco-0.2.14 lib/ruco/history.rb
ruco-0.2.13 lib/ruco/history.rb
ruco-0.2.12 lib/ruco/history.rb
ruco-0.2.11 lib/ruco/history.rb
ruco-0.2.10 lib/ruco/history.rb
ruco-0.2.9 lib/ruco/history.rb
ruco-0.2.8 lib/ruco/history.rb
ruco-0.2.7 lib/ruco/history.rb
ruco-0.2.6 lib/ruco/history.rb