class Unbounded::Range

An unbounded (infinite) range extension for the standard Ruby Range class.

Public Class Methods

humanized(first, last) click to toggle source

@param [Numeric] first @param [Numeric] last @return [String]

# File lib/unbounded/range.rb, line 143
def humanized(first, last)
  return new(first, last).humanized
end
new(*args) click to toggle source

@overload initialize(range_start, range_minimum, exclude_end = false)

Create a range the traditional way, à la `Range.new`.
@param [#succ] range_start
@param [#succ] range_end
@param [Boolean] exclude_end

@overload initialize(range_string)

Create a range in the same manner as you would in PostgreSQL
@param [String] range_string
Calls superclass method
# File lib/unbounded/range.rb, line 19
def initialize(*args)
  parsed = parse_for_range(args)

  @format = parsed.format

  super(parsed.minimum, parsed.maximum, parsed.exclude_end)
end

Private Class Methods

unbounded_endpoint(type, int_to_return) click to toggle source

@param [Symbol] type should be :min or :max @param [Integer] int_to_return integer to return for bitwise comparison in {#unbounded?} @return [void] @!macro [attach] unbounded_endpoint

@!method unbounded_$1imum
  Determine whether the $1 is unbounded.
  @!visibility private
  @return [$2,0] $2 if unbounded, 0 if otherwise

@!method unbounded_$1imum?
  Predicate method for {#unbounded_$1imum} that checks against zero
  @return [Integer,nil]

@!method finite_$1imum?
  Inverse complement of {#unbounded_$1imum?}
  @return [Boolean]
# File lib/unbounded/range.rb, line 164
      def unbounded_endpoint(type, int_to_return)
        attr_name = type == :min ? "begin" : "end"

        class_eval <<-RUBY, __FILE__, __LINE__ + 1
          def unbounded_#{type}imum
            self.#{attr_name}.respond_to?(:infinite?) && self.#{attr_name}.infinite? ? #{int_to_return} : 0
          end

          def unbounded_#{type}imum?
            unbounded_#{type}imum.nonzero?
          end

          def finite_#{type}imum?
            !unbounded_#{type}imum?
          end

          private :unbounded_#{type}imum
        RUBY
      end

Public Instance Methods

count(*args, &block) click to toggle source

@!group Enumerable Overrides Same as `Enumerable#count`, except in cases where the collection is {Range#unbounded?}. @note This would not be true in some cases, e.g. checking for negative

numbers on a range of 0 to infinity.

@return [Integer, INFINITY] Infinity when unbounded, super otherwise

Calls superclass method
# File lib/unbounded/range.rb, line 78
def count(*args, &block)
  unbounded? ? INFINITY : super
end
first(*args) click to toggle source

@overload first

@return [Numeric] equivalent to `#min`

@overload first(n)

@param [Integer] n
@return [Array<#succ>] first n-elements of the range
Calls superclass method
# File lib/unbounded/range.rb, line 87
def first(*args)
  n = args.shift

  if unbounded_minimum? && (n.nil? || n.kind_of?(Integer))
    if n.nil?
      min
    else
      Array.new(n, min)
    end
  else
    return n.nil? ? super() : super(n)
  end
end
humanized() click to toggle source

@todo i18n support @return [String] a more human-readable format

Calls superclass method
# File lib/unbounded/range.rb, line 29
def humanized
  case unbounded?
  when :infinite
    "infinite"
  when :maximum
    "#{self.begin}+"
  when :minimum
    exclude_end? ? "fewer than #{self.end}" : "#{self.end} or fewer"
  else
    super
  end
end
infinite?() click to toggle source

@return [Boolean]

# File lib/unbounded/range.rb, line 43
def infinite?
  numeric? && ( ( unbounded_minimum | unbounded_maximum ) == 3 )
end
last(*args) click to toggle source

@overload last

@return [Numeric] equivalent to {#max}

@overload last(n)

@param  [Integer] n
@return [Array<#succ>] last n-elements of the range
Calls superclass method
# File lib/unbounded/range.rb, line 106
def last(*args)
  n = args.shift

  if unbounded? && (n.nil? || n.kind_of?(Integer))
    if n.nil?
      max
    elsif unbounded? == :minimum # To prevent `cannot iterate from Float`
      new_minimum = max - (n - 1)

      (new_minimum..max).to_a
    else
      Array.new(n, max) # Array of Infinity
    end
  else
    return n.nil? ? super() : super(n)
  end
end
max() click to toggle source

Overload for `Range#max` to account for “unbounded_maximum? && exclude_end?” edge case

Calls superclass method
# File lib/unbounded/range.rb, line 125
def max
  super
rescue TypeError
  self.end
end
minmax() click to toggle source

The default implementation of `Range#minmax` for needlessly uses `#each`, which can cause infinite enumeration. @return [Array(Numeric, Numeric)]

# File lib/unbounded/range.rb, line 134
def minmax
  [min, unbounded? ? INFINITY : max]
end
numeric?() click to toggle source

@return [Boolean] whether this range is numeric

# File lib/unbounded/range.rb, line 48
def numeric?
  self.begin.kind_of?(Numeric) && self.end.kind_of?(Numeric)
end
unbounded() click to toggle source

For compatibility with {Unbounded::RangeExtension#unbounded} unded? @return [self]

# File lib/unbounded/range.rb, line 55
def unbounded
  self
end
unbounded?(unbounded_type = nil) click to toggle source

Check whether this range is unbounded in some way. @return [Symbol,nil] returns a symbol for the type of unboundedness, nil otherwise

# File lib/unbounded/range.rb, line 61
def unbounded?(unbounded_type = nil)
  return false unless numeric?

  unboundedness = case unbounded_minimum | unbounded_maximum
  when 3 then :infinite
  when 2 then :maximum
  when 1 then :minimum
  end

  return unbounded_type && unboundedness ? ( unboundedness == :infinite ) || ( unboundedness == unbounded_type ) : unboundedness
end