Class: FatCore::Column
- Inherits:
-
Object
- Object
- FatCore::Column
- Defined in:
- lib/fat_core/column.rb
Overview
Column objects are just a thin wrapper around an Array to allow columns to be summed and have other operations performed on them, but compacting out nils before proceeding. My original attempt to do this by monkey-patching Array turned out badly. This works much nicer.
Constant Summary collapse
- TYPES =
%w(NilClass TrueClass FalseClass Date DateTime Numeric String)
Instance Attribute Summary collapse
-
#header ⇒ Object
readonly
Returns the value of attribute header.
-
#items ⇒ Object
readonly
Returns the value of attribute items.
-
#type ⇒ Object
readonly
Returns the value of attribute type.
Instance Method Summary collapse
-
#+(other) ⇒ Object
Return a new Column appending the items of other to our items, checking for type compatibility.
- #<<(itm) ⇒ Object
- #[](k) ⇒ Object
- #avg ⇒ Object
-
#convert_to_boolean(val) ⇒ Object
Convert the val to a boolean if it looks like one, otherwise return nil.
-
#convert_to_date_time(val) ⇒ Object
Convert the val to a DateTime if it is either a DateTime, a Date, or a String that can be parsed as a DateTime, otherwise return nil.
-
#convert_to_numeric(val) ⇒ Object
Convert the val to a Numeric if is already a Numberic or is a String that looks like one.
- #convert_to_string(val) ⇒ Object
-
#convert_to_type(val) ⇒ Object
Convert val to the type of key, a ruby class constant, such as Date, Numeric, etc.
- #first ⇒ Object
-
#initialize(header:, type: 'NilClass', items: []) ⇒ Column
constructor
A new instance of Column.
- #last ⇒ Object
- #last_i ⇒ Object
- #max ⇒ Object
- #min ⇒ Object
-
#rng_s ⇒ Object
Return a string that of the first and last values.
- #size ⇒ Object
- #sum ⇒ Object
- #to_a ⇒ Object
Constructor Details
#initialize(header:, type: 'NilClass', items: []) ⇒ Column
Returns a new instance of Column.
11 12 13 14 15 16 |
# File 'lib/fat_core/column.rb', line 11 def initialize(header:, type: 'NilClass', items: []) @header = header.as_sym @type = type raise "Unknown column type '#{type}" unless TYPES.include?(@type.to_s) @items = items end |
Instance Attribute Details
#header ⇒ Object (readonly)
Returns the value of attribute header.
7 8 9 |
# File 'lib/fat_core/column.rb', line 7 def header @header end |
#items ⇒ Object (readonly)
Returns the value of attribute items.
7 8 9 |
# File 'lib/fat_core/column.rb', line 7 def items @items end |
#type ⇒ Object (readonly)
Returns the value of attribute type.
7 8 9 |
# File 'lib/fat_core/column.rb', line 7 def type @type end |
Instance Method Details
#+(other) ⇒ Object
Return a new Column appending the items of other to our items, checking for type compatibility.
40 41 42 43 |
# File 'lib/fat_core/column.rb', line 40 def +(other) raise 'Cannot combine columns with different types' unless type == other.type Column.new(header: header, type: type, items: items + other.items) end |
#<<(itm) ⇒ Object
18 19 20 |
# File 'lib/fat_core/column.rb', line 18 def <<(itm) items << convert_to_type(itm) end |
#[](k) ⇒ Object
22 23 24 |
# File 'lib/fat_core/column.rb', line 22 def [](k) items[k] end |
#avg ⇒ Object
70 71 72 |
# File 'lib/fat_core/column.rb', line 70 def avg sum / items.compact.size.to_d end |
#convert_to_boolean(val) ⇒ Object
Convert the val to a boolean if it looks like one, otherwise return nil. Any boolean or a string of t, f, true, false, y, n, yes, or no, regardless of case is assumed to be a boolean.
141 142 143 144 145 146 147 148 149 150 |
# File 'lib/fat_core/column.rb', line 141 def convert_to_boolean(val) return val if val.is_a?(TrueClass) || val.is_a?(FalseClass) val = val.to_s.clean return nil if val.blank? if val =~ /\Afalse|f|n|no/i false elsif val =~ /\Atrue|t|y|yes\z/i true end end |
#convert_to_date_time(val) ⇒ Object
Convert the val to a DateTime if it is either a DateTime, a Date, or a String that can be parsed as a DateTime, otherwise return nil. It only recognizes strings that contain a something like ‘2016-01-14’ or ‘2/12/1985’ within them, otherwise DateTime.parse would treat many bare numbers as dates, such as ‘2841381’, which it would recognize as a valid date, but the user probably does not intend it to be so treated.
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
# File 'lib/fat_core/column.rb', line 158 def convert_to_date_time(val) return val if val.is_a?(DateTime) return val.to_datetime if val.is_a?(Date) && type == 'DateTime' return val if val.is_a?(Date) begin val = val.to_s.clean return nil if val.blank? return nil unless val =~ %r{\b\d\d\d\d[-/]\d\d?[-/]\d\d?\b} val = DateTime.parse(val.to_s.clean) val = val.to_date if val.seconds_since_midnight.zero? val rescue ArgumentError return nil end end |
#convert_to_numeric(val) ⇒ Object
Convert the val to a Numeric if is already a Numberic or is a String that looks like one. Any Float is promoted to a BigDecimal. Otherwise return nil.
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 |
# File 'lib/fat_core/column.rb', line 177 def convert_to_numeric(val) return BigDecimal.new(val, Float::DIG) if val.is_a?(Float) return val if val.is_a?(Numeric) # Eliminate any commas, $'s, or _'s. val = val.to_s.clean.gsub(/[,_$]/, '') return nil if val.blank? case val when /\A(\d+\.\d*)|(\d*\.\d+)\z/ BigDecimal.new(val.to_s.clean) when /\A[\d]+\z/ val.to_i when %r{\A(\d+)\s*[:/]\s*(\d+)\z} Rational($1, $2) end end |
#convert_to_string(val) ⇒ Object
193 194 195 |
# File 'lib/fat_core/column.rb', line 193 def convert_to_string(val) val.to_s end |
#convert_to_type(val) ⇒ Object
Convert val to the type of key, a ruby class constant, such as Date, Numeric, etc. If type is NilClass, the type is open, and a non-blank val will attempt conversion to one of the allowed types, typing it as a String if no other type is recognized. If the val is blank, and the type is nil, the column type remains open. If the val is nil or a blank and the type is already determined, the val is set to nil, and should be filtered from any column computations. If the val is non-blank and the column type determined, raise an error if the val cannot be converted to the column type. Otherwise, returns the converted val as an object of the correct class.
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
# File 'lib/fat_core/column.rb', line 84 def convert_to_type(val) case type when 'NilClass' if val.blank? # Leave the type of the column open val = nil else # Only non-blank values are allowed to set the type of the column val_class = val.class val = convert_to_boolean(val) || convert_to_date_time(val) || convert_to_numeric(val) || convert_to_string(val) @type = if val.is_a?(Numeric) 'Numeric' else val.class.name end val end when 'TrueClass', 'FalseClass' val_class = val.class val = convert_to_boolean(val) if val.nil? raise "Inconsistent value in a Boolean column #{header} has class #{val_class}" end val when 'DateTime', 'Date' val_class = val.class val = convert_to_date_time(val) unless val raise "Inconsistent value in a DateTime column #{key} has class #{val_class}" end val when 'Numeric' val_class = val.class val = convert_to_numeric(val) unless val raise "Inconsistent value in a Numeric column #{key} has class #{val_class}" end val when 'String' val_class = val.class val = convert_to_string(val) unless val raise "Inconsistent value in a String column #{key} has class #{val_class}" end val else raise "Unknown object of class #{type} in Table" end end |
#first ⇒ Object
45 46 47 |
# File 'lib/fat_core/column.rb', line 45 def first items.compact.first end |
#last ⇒ Object
49 50 51 |
# File 'lib/fat_core/column.rb', line 49 def last items.compact.last end |
#last_i ⇒ Object
34 35 36 |
# File 'lib/fat_core/column.rb', line 34 def last_i size - 1 end |
#max ⇒ Object
66 67 68 |
# File 'lib/fat_core/column.rb', line 66 def max items.compact.max end |
#min ⇒ Object
62 63 64 |
# File 'lib/fat_core/column.rb', line 62 def min items.compact.min end |
#rng_s ⇒ Object
Return a string that of the first and last values.
54 55 56 |
# File 'lib/fat_core/column.rb', line 54 def rng_s "#{first}..#{last}" end |
#size ⇒ Object
30 31 32 |
# File 'lib/fat_core/column.rb', line 30 def size items.size end |
#sum ⇒ Object
58 59 60 |
# File 'lib/fat_core/column.rb', line 58 def sum items.compact.sum end |
#to_a ⇒ Object
26 27 28 |
# File 'lib/fat_core/column.rb', line 26 def to_a items end |