module Pod4::TypeCasting::InstanceMethods
Public Instance Methods
set Octothorpe Guards for everything in the given OT, based on the typecast settings.
# File lib/pod4/typecasting.rb, line 257 def guard(ot) self.class.typecasts.each do |fld, tc| type = tc[:ot_as] || tc[:as] set_guard(ot, fld, type) if type end end
# File lib/pod4/typecasting.rb, line 196 def map_to_interface ot = super hash = typecast_ot(ot, strict: true, mode: :map_to_interface) ot.merge hash end
# File lib/pod4/typecasting.rb, line 180 def map_to_model(ot) enc = self.class.encoding ot.each_value do |v| v.force_encoding(enc) if v.kind_of?(String) && enc end hash = typecast_ot(ot, mode: :map_to_model) super(ot.merge hash) end
# File lib/pod4/typecasting.rb, line 191 def set(ot) hash = typecast_ot(ot, mode: :set) super(ot.merge hash) end
# File lib/pod4/typecasting.rb, line 202 def to_ot ot = super ot2 = ot.merge typecast_ot_to_ot(ot) self.class.typecasts.each do |fld, tc| set_guard(ot2, fld, tc[:ot_as]) if tc[:ot_as] end ot2 end
Return thing cast to type. If opt is true, then return nil if thing cannot be cast to type; otherwise return thing unchanged.
# File lib/pod4/typecasting.rb, line 217 def typecast(type, thing, opt={}) # Nothing to do return thing if type.is_a?(Class) && thing.is_a?(type) # Nothing wrong with nil for our purposes; it's always allowed return thing if thing.nil? # For all current cases, attempting to typecast a blank string should return nil return nil if thing =~ /\A\s*\Z/ # The order we try these in matters return tc_bigdecimal(thing) if type == BigDecimal return tc_float(thing) if type == Float return tc_integer(thing) if type == Integer return tc_date(thing) if type == Date return tc_time(thing) if type == Time return tc_boolean(thing) if type == :boolean fail Pod4Error, "Bad type passed to typecast()" rescue ArgumentError return (opt[:strict] ? nil : thing) end
Return true if the attribute can be cast to the given value. You must name an attribute you specified in a typecast declaration, or you will get an exception. You may pass a value to test, or failing that, we take the current value of the attribute.
# File lib/pod4/typecasting.rb, line 246 def typecast?(attr, val=nil) fail Pod4Error, "Unknown column passed to typecast?()" \ unless (tc = self.class.typecasts[attr]) val = instance_variable_get("@#{attr}".to_sym) if val.nil? !typecast_one(val, tc.merge(strict: true, mode: :typecast?)).nil? end
Private Instance Methods
Set the guard clause for one attribute Note that Time.new returns now, and Date.new returns some date in antiquity. We don't consider those helpful, so we give you 1900-1-1 in both cases
# File lib/pod4/typecasting.rb, line 306 def set_guard(ot, fld, tc) case tc.to_s when "BigDecimal" then ot.guard(fld) { BigDecimal("0") } when "Float" then ot.guard(fld) { Float(0) } when "Integer" then ot.guard(fld) { Integer(0) } when "Date" then ot.guard(fld) { Date.new(1900, 1, 1) } when "Time" then ot.guard(fld) { Time.new(1900, 1, 1) } when "boolean" then ot.guard(fld) { false } end end
# File lib/pod4/typecasting.rb, line 317 def tc_bigdecimal(thing) Float(thing) # BigDecimal sucks at catching bad decimals BigDecimal(thing.to_s) end
# File lib/pod4/typecasting.rb, line 339 def tc_boolean(thing) return thing if thing == true || thing == false return true if %w|true yes y on t 1|.include?(thing.to_s.downcase) return false if %w|false no n off f 0|.include?(thing.to_s.downcase) fail ArgumentError, "Cannot typecast string to Boolean" end
# File lib/pod4/typecasting.rb, line 330 def tc_date(thing) fail ArgumentError, "Can't cast Time to Date" if thing.is_a?(Time) thing.respond_to?(:to_date) ? thing.to_date : Date.parse(thing.to_s) end
# File lib/pod4/typecasting.rb, line 322 def tc_float(thing) Float(thing) end
# File lib/pod4/typecasting.rb, line 326 def tc_integer(thing) Integer(thing.to_s, 10) end
# File lib/pod4/typecasting.rb, line 335 def tc_time(thing) thing.respond_to?(:to_time) ? thing.to_time : Time.parse(thing.to_s) end
Helper for typecast_ot
: cast one attribute
# File lib/pod4/typecasting.rb, line 293 def typecast_one(val, tc) if tc[:use] self.__send__(tc[:use], val, tc) else typecast(tc[:as], val, tc) end end
Return a hash of changes for an OT based on our settings
# File lib/pod4/typecasting.rb, line 269 def typecast_ot(ot, opts={}) hash = {} ot.each do |k,v| tc = self.class.typecasts[k] hash[k] = typecast_one(v, tc.merge(opts)) if tc end hash end
As typecast_ot
, but this is a specific helper for to_ot
# File lib/pod4/typecasting.rb, line 281 def typecast_ot_to_ot(ot) hash = {} ot.each do |k,v| tc = self.class.typecasts[k] hash[k] = (tc && tc[:ot_as]) ? typecast(tc[:ot_as], v) : v end hash end