Похоже, что это ошибка в ActiveSupport.
Вот как можно надежно копировать ее, не прибегая к вставке символов (что часто ненадежно).
Соответствующие кодовые точки:
TM symbol = 0x2122
registered symbol = 0xAE
Код:
$KCODE = 'u'
tm_char = [0x2122].pack('U')
r_char = [0xAE].pack('U')
tm_char.mb_chars.rindex(/\W/) # error: malformed utf-8
r_char.mb_chars.rindex(/\W/) # ok, but I expected 0 instead of nil
tm_char.mb_chars.rindex(tm_char) # ok. but we're not using a regexp
Я подозреваю, что это связано с тем, что TM является 3-байтовым символом UTF-8, а "(R)" является 2-байтовым:
tm_char.bytes.to_a.inspect
r_char.bytes.to_a.inspect
То же самое происходит с mdash (0x2014).
Ruby 1.9.2 не имеет этой проблемы:
[0x2122].pack('U').mb_chars.rindex(/\W/) # => 0
[0x2014].pack('U').mb_chars.rindex(/\W/) # => 0
Вот уродливый обходной путь, чтобы найтипоследний несловесный символ вместе с его индексом.Он даже работает правильно, а не игнорирует многобайтовые символы.
mb_string = "#{tm_char} foo#{tm_char}".mb_chars
match, rev_idx = mb_string.chars.to_a.reverse.each_with_index.detect{|e,idx| e =~ /[^a-zA-Z0-9]/ }
idx = mb_string.size - rev_idx - 1 # => 5