class TinyDyno::Adapter::AttributeValue::Marshaler

Public Instance Methods

format(type: 'auto', obj:) click to toggle source
# File lib/tiny_dyno/adapter/attributes.rb, line 32
def format(type: 'auto', obj:)
  return { null: true } if obj.nil?
  type = obj.class.to_s if type == 'auto'
  case type.to_s
    when 'Hash'
      obj.each.with_object(m:{}) do |(key, value), map|
        map[:m][key.to_s] = format(type: value.class, obj: value)
      end
    when 'Array'
      obj.each.with_object(l:[]) do |value, list|
        list[:l] << format(type: value.class, obj: value)
      end
    when 'String' then { s: obj }
    when 'Symbol' then { s: obj.to_s }
    when 'Numeric', 'Fixnum', 'Float', 'Integer', 'BigDecimal' then numeric_format(type.to_s,obj)
    when 'StringIO', 'IO' then { b: obj }
    when 'Set' then format_set(obj)
    when 'TrueClass', 'FalseClass', 'TinyDyno::Boolean'
      # ToDo, how can we initialize a boolean field into a valid state?
      raise TinyDyno::Errors::InvalidValueType.new(klass: self.class, name: type, value: obj) unless [true,false,nil].include?(obj)
      { bool: obj }
    when 'NilClass' then { null: true }
  else
    msg = "unsupported type, expected Hash, Array, Set, String, Numeric, "
    msg << "IO, true, false, or nil, got #{obj.class.name}"
    raise ArgumentError, msg
  end
end

Private Instance Methods

format_set(set) click to toggle source
# File lib/tiny_dyno/adapter/attributes.rb, line 90
def format_set(set)
  case set.first
    when String, Symbol then { ss: set.map(&:to_s) }
    when Numeric then { ns: set.map(&:to_s) }
    when StringIO, IO then { bs: set.to_a }
    else
      msg = "set types only support String, Numeric, or IO objects"
      raise ArgumentError, msg
  end
end
numeric_format(type,obj) click to toggle source
# File lib/tiny_dyno/adapter/attributes.rb, line 63
def numeric_format(type,obj)
  case type
    when 'Fixnum', 'Integer', 'Numeric'
      if obj.class == BigDecimal
        raise TinyDyno::Errors::NotTransparentlyCoercible.new(klass: self.class, name: type, value: obj) unless obj == BigDecimal.new(obj.to_s)
        { n: obj.to_s }
      elsif obj.class == String
        raise TinyDyno::Errors::NotTransparentlyCoercible.new(klass: self.class, name: type, value: obj) unless obj.to_i.to_s == obj
        { n: obj }
      else
        raise TinyDyno::Errors::NotTransparentlyCoercible.new(klass: self.class, name: type, value: obj) unless obj.to_i == obj.to_s.to_i
        { n: obj.to_s }
      end
    when 'Float'
      raise TinyDyno::Errors::InvalidValueType.new(klass: self.class, name: type, value: obj) unless obj.is_a?(Float)
      raise TinyDyno::Errors::NotTransparentlyCoercible.new(klass: self.class, name: type, value: obj) unless obj == obj.to_s.to_f
      { n: obj.to_s }
    when 'BigDecimal'
      raise TinyDyno::Errors::InvalidValueType.new(klass: self.class, name: type, value: obj) unless obj.is_a?(BigDecimal)
      raise TinyDyno::Errors::NotTransparentlyCoercible.new(klass: self.class, name: type, value: obj) unless obj == BigDecimal.new(obj.to_s)
      { n: obj.to_s}
  else
    msg = "unsupported type, expected Fixnum, Integer, Float, BigDecimal "
    raise ArgumentError, msg
  end
end