module Pod4::TypeCasting::InstanceMethods

Public Instance Methods

guard(ot) click to toggle source

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
map_to_interface() click to toggle source
Calls superclass method
# 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
map_to_model(ot) click to toggle source
Calls superclass method
# 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
set(ot) click to toggle source
Calls superclass method
# File lib/pod4/typecasting.rb, line 191
def set(ot)
  hash = typecast_ot(ot, mode: :set)
  super(ot.merge hash)
end
to_ot() click to toggle source
Calls superclass method
# 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
typecast(type, thing, opt={}) click to toggle source

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
typecast?(attr, val=nil) click to toggle source

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_guard(ot, fld, tc) click to toggle source

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
tc_bigdecimal(thing) click to toggle source
# File lib/pod4/typecasting.rb, line 317
def tc_bigdecimal(thing)
  Float(thing) # BigDecimal sucks at catching bad decimals
  BigDecimal(thing.to_s)
end
tc_boolean(thing) click to toggle source
# 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
tc_date(thing) click to toggle source
# 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
tc_float(thing) click to toggle source
# File lib/pod4/typecasting.rb, line 322
def tc_float(thing)
  Float(thing)
end
tc_integer(thing) click to toggle source
# File lib/pod4/typecasting.rb, line 326
def tc_integer(thing)
  Integer(thing.to_s, 10)
end
tc_time(thing) click to toggle source
# 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
typecast_one(val, tc) click to toggle source

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
typecast_ot(ot, opts={}) click to toggle source

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
typecast_ot_to_ot(ot) click to toggle source

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