Решение Младена работает, если все, что закодировано в ASCII-8BIT, действительно может быть преобразовано непосредственно в UTF-8. Он прерывается, когда есть символы, которые 1) недопустимы или 2) не определены в UTF-8. Тем не менее, это будет работать (в 1.9.2 и выше:
new_str = s.encode('utf-8', 'binary', :invalid => :replace,
:undef => :replace, :replace => '')
ASCII-8BIT является фактически двоичным. Этот код преобразует кодировку в UTF-8, одновременно обрабатывая недопустимые и неопределенные символы. Опция: invalid указывает, что недопустимые символы должны быть заменены. Опция: undef указывает, что неопределенные символы должны быть заменены. А опция: replace определяет, на что следует заменить недопустимые или неопределенные символы. В этом случае я решил просто удалить их.