arkency/rails_event_store

View on GitHub
ruby_event_store/lib/ruby_event_store/specification_result.rb

Summary

Maintainability
B
4 hrs
Test Coverage
# frozen_string_literal: true

module RubyEventStore
  class SpecificationResult
    def initialize(
      direction: :forward,
      start: nil,
      stop: nil,
      older_than: nil,
      older_than_or_equal: nil,
      newer_than: nil,
      newer_than_or_equal: nil,
      time_sort_by: nil,
      count: nil,
      stream: Stream.new(GLOBAL_STREAM),
      read_as: :all,
      batch_size: Specification::DEFAULT_BATCH_SIZE,
      with_ids: nil,
      with_types: nil
    )
      @attributes =
        Struct
          .new(
            :direction,
            :start,
            :stop,
            :older_than,
            :older_than_or_equal,
            :newer_than,
            :newer_than_or_equal,
            :time_sort_by,
            :count,
            :stream,
            :read_as,
            :batch_size,
            :with_ids,
            :with_types
          )
          .new(
            direction,
            start,
            stop,
            older_than,
            older_than_or_equal,
            newer_than,
            newer_than_or_equal,
            time_sort_by,
            count,
            stream,
            read_as,
            batch_size,
            with_ids,
            with_types
          )
      freeze
    end

    # Limited results. True if number of read elements are limited
    # {http://railseventstore.org/docs/read/ Find out more}.
    #
    # @return [Boolean]
    def limit?
      !attributes.count.nil?
    end

    # Results limit or infinity if limit not defined
    # {http://railseventstore.org/docs/read/ Find out more}.
    #
    # @return [Integer|Infinity]
    def limit
      attributes.count || Float::INFINITY
    end

    # Stream definition. Stream to be read or nil
    # {http://railseventstore.org/docs/read/ Find out more}.
    #
    # @return [Stream|nil]
    def stream
      attributes.stream
    end

    # Starting position. Event id of starting event
    # {http://railseventstore.org/docs/read/ Find out more}.
    #
    # @return [String]
    def start
      attributes.start
    end

    # Stop position. Event id of stopping event
    # {http://railseventstore.org/docs/read/ Find out more}.
    #
    # @return [String|Symbol]
    def stop
      attributes.stop
    end

    # Ending time.
    # {http://railseventstore.org/docs/read/ Find out more}.
    #
    # @return [Time]
    def older_than
      attributes.older_than
    end

    # Ending time.
    # {http://railseventstore.org/docs/read/ Find out more}.
    #
    # @return [Time]
    def older_than_or_equal
      attributes.older_than_or_equal
    end

    # Starting time.
    # {http://railseventstore.org/docs/read/ Find out more}.
    #
    # @return [Time]
    def newer_than
      attributes.newer_than
    end

    # Starting time.
    # {http://railseventstore.org/docs/read/ Find out more}.
    #
    # @return [Time]
    def newer_than_or_equal
      attributes.newer_than_or_equal
    end

    # Time sorting strategy. Nil when not specified.
    # {http://railseventstore.org/docs/read/ Find out more}.
    #
    # @return [Symbol]
    def time_sort_by
      attributes.time_sort_by
    end

    # Read direction. True is reading forward
    # {http://railseventstore.org/docs/read/ Find out more}.
    #
    # @return [Boolean]
    def forward?
      get_direction.equal?(:forward)
    end

    # Read direction. True is reading backward
    # {http://railseventstore.org/docs/read/ Find out more}.
    #
    # @return [Boolean]
    def backward?
      get_direction.equal?(:backward)
    end

    # Size of batch to read (only for :batch read strategy)
    # {http://railseventstore.org/docs/read/ Find out more}.
    #
    # @return [Integer]
    def batch_size
      attributes.batch_size
    end

    # Ids of specified event to be read (if any given)
    # {http://railseventstore.org/docs/read/ Find out more}.
    #
    # @return [Array|nil]
    def with_ids
      attributes.with_ids
    end

    # Read by specified ids. True if event ids have been specified.
    # {http://railseventstore.org/docs/read/ Find out more}.
    #
    # @return [Boolean]
    def with_ids?
      !with_ids.nil?
    end

    # Event types to be read (if any given)
    # {http://railseventstore.org/docs/read/ Find out more}.
    #
    # @return [Array|nil]
    def with_types
      attributes.with_types&.map(&:to_s)
    end

    # Read by specified event types. True if event types have been specified.
    # {http://railseventstore.org/docs/read/ Find out more}.
    #
    # @return [Boolean]
    def with_types?
      !(with_types || []).empty?
    end

    # Read strategy. True if items will be read in batches
    # {http://railseventstore.org/docs/read/ Find out more}.
    #
    # @return [Boolean]
    def batched?
      attributes.read_as.equal?(:batch)
    end

    # Read strategy. True if first item will be read
    # {http://railseventstore.org/docs/read/ Find out more}.
    #
    # @return [Boolean]
    def first?
      attributes.read_as.equal?(:first)
    end

    # Read strategy. True if last item will be read
    # {http://railseventstore.org/docs/read/ Find out more}.
    #
    # @return [Boolean]
    def last?
      attributes.read_as.equal?(:last)
    end

    # Read strategy. True if all items will be read
    # {http://railseventstore.org/docs/read/ Find out more}.
    #
    # @return [Boolean]
    def all?
      attributes.read_as.equal?(:all)
    end

    # Read strategy. True if results will be sorted by timestamp
    # {http://railseventstore.org/docs/read/ Find out more}.
    #
    # @return [Boolean]
    def time_sort_by_as_at?
      time_sort_by.equal?(:as_at)
    end

    # Read strategy. True if results will be sorted by valid_at
    # {http://railseventstore.org/docs/read/ Find out more}.
    #
    # @return [Boolean]
    def time_sort_by_as_of?
      time_sort_by.equal?(:as_of)
    end

    # Clone [SpecificationResult]
    # If block is given cloned attributes might be modified.
    #
    # @return [SpecificationResult]
    def dup
      new_attributes = attributes.dup
      yield new_attributes if block_given?
      SpecificationResult.new(**new_attributes.to_h)
    end

    # Two specification attributess are equal if:
    # * they are of the same class
    # * have identical data (verified with eql? method)
    #
    # @param other_spec [SpecificationResult, Object] object to compare
    #
    # @return [TrueClass, FalseClass]
    def ==(other_spec)
      other_spec.hash.eql?(hash)
    end

    # Generates a Fixnum hash value for this object. This function
    # have the property that a.eql?(b) implies a.hash == b.hash.
    #
    # The hash value is used along with eql? by the Hash class to
    # determine if two objects reference the same hash key.
    #
    # This hash is based on
    # * class
    # * direction
    # * start
    # * stop
    # * older_than
    # * older_than_or_equal
    # * newer_than
    # * newer_than_or_equal
    # * time_sort_by
    # * count
    # * stream
    # * read_as
    # * batch_size
    # * with_ids
    # * with_types
    #
    # @return [Integer]
    def hash
      [
        get_direction,
        start,
        stop,
        older_than,
        older_than_or_equal,
        newer_than,
        newer_than_or_equal,
        time_sort_by,
        limit,
        stream,
        attributes.read_as,
        batch_size,
        with_ids,
        with_types
      ].hash ^ self.class.hash
    end

    private

    attr_reader :attributes

    def get_direction
      attributes.direction
    end
  end
end