Module: FatTable::Convert
- Defined in:
- lib/fat_table/convert.rb
Constant Summary collapse
- ISO_DATE_RE =
%r{\A(?<yr>\d\d\d\d)[-\/] (?<mo>\d\d?)[-\/] (?<dy>\d\d?)\s* (T?\s*\d\d:\d\d(:\d\d)?\s* ([-+](\d\d?)(:\d\d?))?)?\s* ((mon|tue|wed|thu|fri|sat|sun)[a-zA-z]*)?\s* \z}xi
- AMR_DATE_RE =
%r{\A(?<dy>\d\d?)[-/](?<mo>\d\d?)[-/](?<yr>\d\d\d\d)\s* (?<tm>T\d\d:\d\d:\d\d(\+\d\d:\d\d)?)?\z}xi
- INV_DATE_RE =
A Date like 'Tue, 01 Nov 2016' or 'Tue 01 Nov 2016' or '01 Nov 2016'. These are emitted by Postgresql, so it makes from_sql constructor possible without special formatting of the dates.
%r{\A((mon|tue|wed|thu|fri|sat|sun)[a-zA-z]*,?)?\s+ # looks like dow (?<dy>\d\d?)\s+ # one or two-digit day (?<mo_name>[jfmasondJFMASOND][A-Za-z]{2,})\s+ # looks like a month name (?<yr>\d\d\d\d) # and a 4-digit year \z}xi
Class Method Summary collapse
-
.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, a Time, 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 Numeric or is a String that looks like one.
- .convert_to_string(val) ⇒ Object
-
.convert_to_type(val, type, tolerant: false) ⇒ Object
Convert val to the type of key, a ruby class constant, such as Date, Numeric, etc.
Class Method Details
.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.
81 82 83 84 85 86 87 88 89 90 |
# File 'lib/fat_table/convert.rb', line 81 def self.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.match?(/\A(false|f|n|no)\z/i) false elsif val.match?(/\A(true|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, a Time, 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.
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/fat_table/convert.rb', line 118 def self.convert_to_date_time(val) return val if val.is_a?(DateTime) return val if val.is_a?(Date) return val.to_datetime if val.is_a?(Time) begin str = val.to_s.clean.sub(/\A[\[\(\{\<]\s*/, '').sub(/[\]\)\}\>]\s*\z/, '') return nil if str.blank? if str.match(ISO_DATE_RE) date = DateTime.parse(val) elsif str =~ AMR_DATE_RE date = DateTime.new(Regexp.last_match[:yr].to_i, Regexp.last_match[:mo].to_i, Regexp.last_match[:dy].to_i) elsif str =~ INV_DATE_RE mo = Date.mo_name_to_num(last_match[:mo_name]) date = DateTime.new(Regexp.last_match[:yr].to_i, mo, Regexp.last_match[:dy].to_i) else return nil end # val = val.to_date if date.seconds_since_midnight.zero? ? date.to_date : date rescue ArgumentError nil end end |
.convert_to_numeric(val) ⇒ Object
Convert the val to a Numeric if is already a Numeric or is a String that looks like one. Any Float is promoted to a BigDecimal. Otherwise return nil.
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 |
# File 'lib/fat_table/convert.rb', line 150 def self.convert_to_numeric(val) return BigDecimal(val, Float::DIG) if val.is_a?(Float) return val if val.is_a?(Numeric) # Eliminate any commas, $'s (or other currency symbol), or _'s. cursym = Regexp.quote(FatTable.currency_symbol) clean_re = /[,_#{cursym}]/ val = val.to_s.clean.gsub(clean_re, '') return nil if val.blank? case val when /\A[-+]?\d+\.\z/ # Catch quirk in Ruby's BigDecimal converter where a number ending in # a decimal but with no digits after the decimal throws an # ArgumentError as an invalid value for BigDecimal(). Just append a # '0'. val += '0' BigDecimal(val.to_s.clean) when /(\A[-+]?\d+\.\d+\z)|(\A[-+]?\d*\.\d+\z)/ BigDecimal(val.to_s.clean) when /\A[-+]?[\d]+\z/ val.to_i when %r{\A(?<nm>[-+]?\d+)\s*[:/]\s*(?<dn>[-+]?\d+)\z} Rational(Regexp.last_match[:nm], Regexp.last_match[:dn]) end end |
.convert_to_string(val) ⇒ Object
177 178 179 |
# File 'lib/fat_table/convert.rb', line 177 def self.convert_to_string(val) val.to_s end |
.convert_to_type(val, type, tolerant: false) ⇒ 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.
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/fat_table/convert.rb', line 13 def self.convert_to_type(val, type, tolerant: false) case type when 'NilClass' if val != false && val.blank? # Leave the type of the Column open. Unfortunately, false counts as # blank and we don't want it to. It should be classified as a boolean. new_val = nil else # Only non-blank values are allowed to set the type of the Column bool_val = convert_to_boolean(val) new_val = if bool_val.nil? convert_to_date_time(val) || convert_to_numeric(val) || convert_to_string(val) else bool_val end end new_val when 'Boolean' if val.is_a?(String) && val.blank? || val.nil? nil else new_val = convert_to_boolean(val) if new_val.nil? raise IncompatibleTypeError end new_val end when 'DateTime' if val.blank? nil else new_val = convert_to_date_time(val) if new_val.nil? raise IncompatibleTypeError end new_val end when 'Numeric' if val.blank? nil else new_val = convert_to_numeric(val) if new_val.nil? raise IncompatibleTypeError end new_val end when 'String' if val.nil? nil else new_val = convert_to_string(val) if new_val.nil? raise IncompatibleTypeError end new_val end else raise LogicError, "Mysteriously, column has unknown type '#{type}'" end end |