class HashSchema def initialize(schema) @schema = schema.map { |key, type| [key, HashSchema.lookup(type)] }.to_h end def cast(params) params.map { |key, value| [key, @schema[key] ? @schema[key].cast(value) : value] }.to_h end class << self def lookup(type) case type when Array then ArraySchema.new(type[0]) when Hash then HashSchema.new(type) when Symbol then ActiveModel::Type.lookup(type) else type end end end class ArraySchema def initialize(type) @type = HashSchema.lookup(type) end def cast(values) values.map { |value| @type.cast(value) } end end end