класс ActiveSupport::Multibyte::Chars
Многобайтовые символы Active Support
Chars позволяет прозрачно работать с кодировкой UTF-8 в классе Ruby String, не обладая обширными знаниями о кодировках. Объект Chars принимает строку при инициализации и безопасно с точки зрения кодировки проксирует методы String. В прокси также реализованы все обычные методы String.
Методы String проксируются через объект Chars и доступны через метод mb_chars. Методы, которые обычно возвращают объект String, теперь возвращают объект Chars, что позволяет вызывать методы цепочкой.
'The Perfect String '.mb_chars.downcase.strip # => #<ActiveSupport::Multibyte::Chars:0x007fdc434ccc10 @wrapped_string="the perfect string">
Объекты Chars полностью взаимозаменяемы с объектами String, если не выполняются явные проверки класса. Если некоторые методы явно проверяют класс, вызовите to_s, прежде чем передавать им объекты chars.
bad.explicit_checking_method 'T'.mb_chars.downcase.to_s
Реализация Chars по умолчанию предполагает, что строка закодирована в UTF-8. Если требуется обрабатывать другие кодировки, можно написать собственный обработчик многобайтовых строк и настроить его с помощью ActiveSupport::Multibyte.proxy_class.
class CharsForUTF32
def size
@wrapped_string.size / 4
end
def self.accepts?(string)
string.length % 4 == 0
end
end
ActiveSupport::Multibyte.proxy_class = CharsForUTF32
Атрибуты
Публичные методы класса
# File activesupport/lib/active_support/multibyte/chars.rb, line 56
def initialize(string, deprecation: true)
if deprecation
ActiveSupport.deprecator.warn(
"ActiveSupport::Multibyte::Chars is deprecated and will be removed in Rails 8.2. " \
"Use normal string methods instead."
)
end
@wrapped_string = string
if string.encoding != Encoding::UTF_8
@wrapped_string = @wrapped_string.dup
@wrapped_string.force_encoding(Encoding::UTF_8)
end
end Создаёт новый экземпляр Chars, оборачивая string.
Публичные методы экземпляра
# File activesupport/lib/active_support/multibyte/chars.rb, line 150
def compose
chars(Unicode.compose(@wrapped_string.codepoints.to_a).pack("U*"))
end Выполняет композицию всех символов.
'é'.length # => 1 'é'.mb_chars.compose.to_s.length # => 1
# File activesupport/lib/active_support/multibyte/chars.rb, line 142
def decompose
chars(Unicode.decompose(:canonical, @wrapped_string.codepoints.to_a).pack("U*"))
end Выполняет каноническую декомпозицию всех символов.
'é'.length # => 1 'é'.mb_chars.decompose.to_s.length # => 2
# File activesupport/lib/active_support/multibyte/chars.rb, line 158 def grapheme_length @wrapped_string.grapheme_clusters.length end
Возвращает количество графемных кластеров в строке.
'क्षि'.mb_chars.length # => 4 'क्षि'.mb_chars.grapheme_length # => 2
# File activesupport/lib/active_support/multibyte/chars.rb, line 125 def limit(limit) chars(@wrapped_string.truncate_bytes(limit, omission: nil)) end
Ограничивает размер строки в байтах заданным количеством байтов, не разрывая символы. Этот метод можно использовать, если по какой-либо причине объём памяти для хранения строки ограничен.
'こんにちは'.mb_chars.limit(7).to_s # => "こん"
# File activesupport/lib/active_support/multibyte/chars.rb, line 72
def method_missing(method, ...)
result = @wrapped_string.__send__(method, ...)
if method.end_with?("!")
self if result
else
result.kind_of?(String) ? chars(result) : result
end
end Перенаправляет все неопределённые методы обёрнутой строке.
# File activesupport/lib/active_support/multibyte/chars.rb, line 84 def respond_to_missing?(method, include_private) @wrapped_string.respond_to?(method, include_private) end
Возвращает true, если obj отвечает на указанный метод. Приватные методы учитываются при поиске, только если значение необязательного второго параметра равно true.
# File activesupport/lib/active_support/multibyte/chars.rb, line 116 def reverse chars(@wrapped_string.grapheme_clusters.reverse.join) end
Меняет порядок всех символов в строке на обратный.
'Café'.mb_chars.reverse.to_s # => 'éfaC'
# File activesupport/lib/active_support/multibyte/chars.rb, line 106
def slice!(*args)
string_sliced = @wrapped_string.slice!(*args)
if string_sliced
chars(string_sliced)
end
end Работает как String#slice!, но возвращает экземпляр Chars или nil, если строка не была изменена. Строка не изменится, если указанный диапазон выходит за её границы.
string = 'Welcome' string.mb_chars.slice!(3) # => #<ActiveSupport::Multibyte::Chars:0x000000038109b8 @wrapped_string="c"> string # => 'Welome' string.mb_chars.slice!(0..3) # => #<ActiveSupport::Multibyte::Chars:0x00000002eb80a0 @wrapped_string="Welo"> string # => 'me'
# File activesupport/lib/active_support/multibyte/chars.rb, line 93
def split(*args)
@wrapped_string.split(*args).map { |i| self.class.new(i) }
end Работает так же, как String#split, за исключением того, что элементы результирующего списка являются экземплярами Chars, а не String. Это упрощает цепочку вызовов методов.
'Café périferôl'.mb_chars.split(/é/).map { |part| part.upcase.to_s } # => ["CAF", " P", "RIFERÔL"]
# File activesupport/lib/active_support/multibyte/chars.rb, line 167 def tidy_bytes(force = false) chars(Unicode.tidy_bytes(@wrapped_string, force)) end
Заменяет все символы ISO-8859-1 или CP1252 их эквивалентами в UTF-8, в результате чего получается корректная строка UTF-8.
Передача true принудительно нормализует все байты, предполагая, что строка целиком закодирована в CP1252 или ISO-8859-1.
# File activesupport/lib/active_support/multibyte/chars.rb, line 133
def titleize
chars(downcase.to_s.gsub(/\b('?\S)/u) { $1.upcase })
end По возможности переводит первую букву каждого слова в верхний регистр.
"ÉL QUE SE ENTERÓ".mb_chars.titleize.to_s # => "Él Que Se Enteró" "日本語".mb_chars.titleize.to_s # => "日本語"
© 2004–2021 David Heinemeier Hansson
Licensed under the MIT License.