Class: Unbounded::Range
- Inherits:
-
Range
- Object
- Range
- Unbounded::Range
- Includes:
- Formats
- Defined in:
- lib/unbounded/range.rb
Overview
An unbounded (infinite) range extension for the standard Ruby Range class.
Constant Summary
Constants included from Formats
Formats::POSTGRES_FORMAT, Formats::SIMPLE_FORMAT
Enumerable Overrides collapse
- .humanized(first, last) ⇒ String
- .unbounded_endpoint(type, int_to_return) ⇒ void private
-
#count(*args, &block) ⇒ Integer, INFINITY
Same as
Enumerable#count
, except in cases where the collection is #unbounded?. -
#finite_maximum? ⇒ Boolean
Inverse complement of #unbounded_maximum?.
-
#finite_minimum? ⇒ Boolean
Inverse complement of #unbounded_minimum?.
- #first(*args) ⇒ Object
- #last(*args) ⇒ Object
-
#max ⇒ Object
Overload for
Range#max
to account for "unbounded_maximum? && exclude_end?" edge case. -
#minmax ⇒ Array(Numeric, Numeric)
The default implementation of
Range#minmax
for needlessly uses#each
, which can cause infinite enumeration. -
#unbounded_maximum ⇒ 2, 0
private
Determine whether the max is unbounded.
-
#unbounded_maximum? ⇒ Integer?
Predicate method for #unbounded_maximum that checks against zero.
-
#unbounded_minimum ⇒ 1, 0
private
Determine whether the min is unbounded.
-
#unbounded_minimum? ⇒ Integer?
Predicate method for #unbounded_minimum that checks against zero.
Instance Method Summary collapse
-
#humanized ⇒ String
A more human-readable format.
- #infinite? ⇒ Boolean
-
#initialize(*args) ⇒ Range
constructor
A new instance of Range.
-
#numeric? ⇒ Boolean
Whether this range is numeric.
-
#unbounded ⇒ self
For compatibility with Unbounded::RangeExtension#unbounded unded?.
-
#unbounded?(unbounded_type = nil) ⇒ Symbol?
Check whether this range is unbounded in some way.
Methods included from Formats
#alter_by_postgres_style!, #alter_by_simple_style!, #parse_for_range, #parse_standard_range_options, #parse_string_for_range_options
Methods included from Utility
Constructor Details
#initialize(range_start, range_minimum, exclude_end = false) ⇒ Range #initialize(range_string) ⇒ Range
Returns a new instance of Range.
19 20 21 22 23 24 25 |
# 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 |
Class Method Details
.humanized(first, last) ⇒ String
143 144 145 |
# File 'lib/unbounded/range.rb', line 143 def humanized(first, last) return new(first, last).humanized end |
.unbounded_endpoint(type, int_to_return) ⇒ void (private)
This method returns an undefined value.
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
# 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 |
Instance Method Details
#count(*args, &block) ⇒ Integer, INFINITY
This would not be true in some cases, e.g. checking for negative numbers on a range of 0 to infinity.
Same as Enumerable#count
, except in cases where the collection is #unbounded?.
78 79 80 |
# File 'lib/unbounded/range.rb', line 78 def count(*args, &block) unbounded? ? INFINITY : super end |
#finite_maximum? ⇒ Boolean
Inverse complement of #unbounded_maximum?
186 |
# File 'lib/unbounded/range.rb', line 186 unbounded_endpoint :max, 2 |
#finite_minimum? ⇒ Boolean
Inverse complement of #unbounded_minimum?
185 |
# File 'lib/unbounded/range.rb', line 185 unbounded_endpoint :min, 1 |
#first ⇒ Numeric #first(n) ⇒ Array<#succ>
87 88 89 90 91 92 93 94 95 96 97 98 99 |
# 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 ⇒ String
i18n support
Returns a more human-readable format.
29 30 31 32 33 34 35 36 37 38 39 40 |
# 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? ⇒ Boolean
43 44 45 |
# File 'lib/unbounded/range.rb', line 43 def infinite? numeric? && ( ( unbounded_minimum | unbounded_maximum ) == 3 ) end |
#last ⇒ Numeric #last(n) ⇒ Array<#succ>
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
# 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 ⇒ Object
Overload for Range#max
to account for "unbounded_maximum? && exclude_end?" edge case
125 126 127 128 129 |
# File 'lib/unbounded/range.rb', line 125 def max super rescue TypeError self.end end |
#minmax ⇒ Array(Numeric, Numeric)
The default implementation of Range#minmax
for needlessly uses #each
,
which can cause infinite enumeration.
134 135 136 |
# File 'lib/unbounded/range.rb', line 134 def minmax [min, unbounded? ? INFINITY : max] end |
#numeric? ⇒ Boolean
Returns whether this range is numeric.
48 49 50 |
# File 'lib/unbounded/range.rb', line 48 def numeric? self.begin.kind_of?(Numeric) && self.end.kind_of?(Numeric) end |
#unbounded ⇒ self
For compatibility with Unbounded::RangeExtension#unbounded unded?
55 56 57 |
# File 'lib/unbounded/range.rb', line 55 def unbounded self end |
#unbounded?(unbounded_type = nil) ⇒ Symbol?
Check whether this range is unbounded in some way.
61 62 63 64 65 66 67 68 69 70 71 |
# 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 |
#unbounded_maximum ⇒ 2, 0 (private)
Determine whether the max is unbounded.
186 |
# File 'lib/unbounded/range.rb', line 186 unbounded_endpoint :max, 2 |
#unbounded_maximum? ⇒ Integer?
Predicate method for #unbounded_maximum that checks against zero
186 |
# File 'lib/unbounded/range.rb', line 186 unbounded_endpoint :max, 2 |
#unbounded_minimum ⇒ 1, 0 (private)
Determine whether the min is unbounded.
185 |
# File 'lib/unbounded/range.rb', line 185 unbounded_endpoint :min, 1 |
#unbounded_minimum? ⇒ Integer?
Predicate method for #unbounded_minimum that checks against zero
185 |
# File 'lib/unbounded/range.rb', line 185 unbounded_endpoint :min, 1 |