跳至内容 跳至搜索

Active Support Multibyte Chars

Chars 使您无需深入了解编码知识,即可透明地使用 Ruby String 类中的 UTF-8 编码。 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 对象完全可互换,只要不进行显式的类检查。如果某些方法显式检查类,请在将 chars 对象传递给它们之前调用 to_s

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
方法
C
D
G
L
M
N
R
S
T
包含的模块

Attributes

[R] to_s
[R] to_str
[R] wrapped_string

类公共方法

new(string, deprecation: true)

通过包装 string 创建一个新的 Chars 实例。

# 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

实例公共方法

compose()

对所有字符执行组合。

'é'.length                       # => 1
'é'.mb_chars.compose.to_s.length # => 1
# File activesupport/lib/active_support/multibyte/chars.rb, line 150
def compose
  chars(Unicode.compose(@wrapped_string.codepoints.to_a).pack("U*"))
end

decompose()

对所有字符执行规范分解。

'é'.length                         # => 1
'é'.mb_chars.decompose.to_s.length # => 2
# File activesupport/lib/active_support/multibyte/chars.rb, line 142
def decompose
  chars(Unicode.decompose(:canonical, @wrapped_string.codepoints.to_a).pack("U*"))
end

grapheme_length()

返回字符串中字位簇的数量。

'क्षि'.mb_chars.length   # => 4
'क्षि'.mb_chars.grapheme_length # => 2
# File activesupport/lib/active_support/multibyte/chars.rb, line 158
def grapheme_length
  @wrapped_string.grapheme_clusters.length
end

limit(limit)

将字符串的字节大小限制在特定字节数,而不破坏字符。当字符串存储空间有限时可用。

'こんにちは'.mb_chars.limit(7).to_s # => "こん"
# File activesupport/lib/active_support/multibyte/chars.rb, line 125
def limit(limit)
  chars(@wrapped_string.truncate_bytes(limit, omission: nil))
end

method_missing(method, ...)

将所有未定义的调用转发给包装的字符串。

# 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

respond_to_missing?(method, include_private)

如果 obj 响应给定的方法,则返回 true。仅当可选的第二个参数评估为 true 时,才会在搜索中包含私有方法。

# 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

reverse()

反转字符串中的所有字符。

'Café'.mb_chars.reverse.to_s # => 'éfaC'
# File activesupport/lib/active_support/multibyte/chars.rb, line 116
def reverse
  chars(@wrapped_string.grapheme_clusters.reverse.join)
end

slice!(*args)

工作方式类似于 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 106
def slice!(*args)
  string_sliced = @wrapped_string.slice!(*args)
  if string_sliced
    chars(string_sliced)
  end
end

split(*args)

工作方式与 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 93
def split(*args)
  @wrapped_string.split(*args).map { |i| self.class.new(i) }
end

tidy_bytes(force = false)

将所有 ISO-8859-1 或 CP1252 字符替换为它们的 UTF-8 等效字符,从而生成一个有效的 UTF-8 字符串。

传递 true 将强制清理所有字节,假设字符串的编码完全是 CP1252 或 ISO-8859-1。

# File activesupport/lib/active_support/multibyte/chars.rb, line 167
def tidy_bytes(force = false)
  chars(Unicode.tidy_bytes(@wrapped_string, force))
end

titlecase()

别名:titleize

titleize()

在每个单词的首字母大写(如果可能)。

"ÉL QUE SE ENTERÓ".mb_chars.titleize.to_s    # => "Él Que Se Enteró"
"日本語".mb_chars.titleize.to_s               # => "日本語"
也别名为:titlecase
# File activesupport/lib/active_support/multibyte/chars.rb, line 133
def titleize
  chars(downcase.to_s.gsub(/\b('?\S)/u) { $1.upcase })
end