Active Support Inflector
The Inflector
transforms words from singular to plural, class names to table names, modularized class names to ones without, and class names to foreign keys. The default inflections for pluralization, singularization, and uncountable words are kept in inflections.rb.
The Rails core team has stated patches for the inflections library will not be accepted in order to avoid breaking legacy applications which may be relying on errant inflections. If you discover an incorrect inflection and require it for your application or wish to define rules for languages other than English, please correct or add them yourself (explained below).
- C
- D
- F
- H
- I
- O
- P
- S
- T
- U
常量
ALLOWED_ENCODINGS_FOR_TRANSLITERATE | = | [Encoding::UTF_8, Encoding::US_ASCII, Encoding::GB18030].freeze |
实例公共方法
camelize(term, uppercase_first_letter = true) 链接
将字符串转换为 UpperCamelCase。如果uppercase_first_letter
参数设置为 false,则生成 lowerCamelCase。
还会将 ‘/’ 转换为 ‘::’,这对于将路径转换为命名空间很有用。
camelize('active_model') # => "ActiveModel"
camelize('active_model', false) # => "activeModel"
camelize('active_model/errors') # => "ActiveModel::Errors"
camelize('active_model/errors', false) # => "activeModel::Errors"
作为经验法则,您可以将camelize
视为 underscore
的逆运算,尽管在某些情况下并非如此
camelize(underscore('SSLError')) # => "SslError"
源代码:显示 | 在 GitHub 上
# File activesupport/lib/active_support/inflector/methods.rb, line 70 def camelize(term, uppercase_first_letter = true) string = term.to_s # String#camelize takes a symbol (:upper or :lower), so here we also support :lower to keep the methods consistent. if !uppercase_first_letter || uppercase_first_letter == :lower string = string.sub(inflections.acronyms_camelize_regex) { |match| match.downcase! || match } elsif string.match?(/\A[a-z\d]*\z/) return inflections.acronyms[string]&.dup || string.capitalize else string = string.sub(/^[a-z\d]*/) { |match| inflections.acronyms[match] || match.capitalize! || match } end string.gsub!(/(?:_|(\/))([a-z\d]*)/i) do word = $2 substituted = inflections.acronyms[word] || word.capitalize! || word $1 ? "::#{substituted}" : substituted end string end
classify(table_name) 链接
从复数表名创建类名,就像 Rails 对表名到模型所做的那样。请注意,这将返回一个字符串,而不是一个 类
。(要转换为实际的类,请在classify
后面使用 constantize
。)
classify('ham_and_eggs') # => "HamAndEgg"
classify('posts') # => "Post"
单数名称处理不正确
classify('calculus') # => "Calculu"
源代码:显示 | 在 GitHub 上
# File activesupport/lib/active_support/inflector/methods.rb, line 218 def classify(table_name) # strip out any leading schema name camelize(singularize(table_name.to_s.sub(/.*\./, ""))) end
constantize(camel_cased_word) 链接
尝试查找与参数字符串中指定名称相同的常量。
constantize('Module') # => Module
constantize('Foo::Bar') # => Foo::Bar
无论名称是否以“::”开头,都假定它是顶级常量的名称。不考虑任何词法上下文
C = 'outside'
module M
C = 'inside'
C # => 'inside'
constantize('C') # => 'outside', same as ::C
end
当名称不是 CamelCase 或常量未知时,会引发 NameError
。
源代码:显示 | 在 GitHub 上
# File activesupport/lib/active_support/inflector/methods.rb, line 289 def constantize(camel_cased_word) Object.const_get(camel_cased_word) end
dasherize(underscored_word) 链接
将字符串中的下划线替换为连字符。
dasherize('puni_puni') # => "puni-puni"
源代码:显示 | 在 GitHub 上
# File activesupport/lib/active_support/inflector/methods.rb, line 226 def dasherize(underscored_word) underscored_word.tr("_", "-") end
deconstantize(path) 链接
从字符串中的常量表达式中删除最右边的段。
deconstantize('Net::HTTP') # => "Net"
deconstantize('::Net::HTTP') # => "::Net"
deconstantize('String') # => ""
deconstantize('::String') # => ""
deconstantize('') # => ""
另请参见 demodulize
。
源代码:显示 | 在 GitHub 上
# File activesupport/lib/active_support/inflector/methods.rb, line 256 def deconstantize(path) path.to_s[0, path.rindex("::") || 0] # implementation based on the one in facets' Module#spacename end
demodulize(path) 链接
从字符串中的表达式中删除模块部分。
demodulize('ActiveSupport::Inflector::Inflections') # => "Inflections"
demodulize('Inflections') # => "Inflections"
demodulize('::Inflections') # => "Inflections"
demodulize('') # => ""
另请参见 deconstantize
。
源代码:显示 | 在 GitHub 上
# File activesupport/lib/active_support/inflector/methods.rb, line 238 def demodulize(path) path = path.to_s if i = path.rindex("::") path[(i + 2), path.length] else path end end
downcase_first(string) 链接
将字符串中的第一个字符转换为小写。
downcase_first('If they enjoyed The Matrix') # => "if they enjoyed The Matrix"
downcase_first('I') # => "i"
downcase_first('') # => ""
源代码:显示 | 在 GitHub 上
# File activesupport/lib/active_support/inflector/methods.rb, line 175 def downcase_first(string) string.length > 0 ? string[0].downcase.concat(string[1..-1]) : +"" end
foreign_key(class_name, separate_class_name_and_id_with_underscore = true) 链接
从类名创建外键名称。separate_class_name_and_id_with_underscore
设置方法是否应在名称和“id”之间放置“_”。
foreign_key('Message') # => "message_id"
foreign_key('Message', false) # => "messageid"
foreign_key('Admin::Post') # => "post_id"
源代码:显示 | 在 GitHub 上
# File activesupport/lib/active_support/inflector/methods.rb, line 267 def foreign_key(class_name, separate_class_name_and_id_with_underscore = true) underscore(demodulize(class_name)) + (separate_class_name_and_id_with_underscore ? "_id" : "id") end
humanize(lower_case_and_underscored_word, capitalize: true, keep_id_suffix: false) 链接
调整属性名称以供最终用户显示。
具体来说,执行以下转换
-
将人类变格规则应用于参数。
-
删除任何前导下划线。
-
如果存在,删除“_id”后缀。
-
将任何下划线替换为空格。
-
将所有单词(除缩略词外)转换为小写。
-
将第一个单词的首字母大写。
可以通过将:capitalize
选项设置为 false 来关闭第一个单词的首字母大写(默认为 true)。
可以通过将可选参数keep_id_suffix
设置为 true 来保留尾部的“_id”并将其大写(默认为 false)。
humanize('employee_salary') # => "Employee salary"
humanize('author_id') # => "Author"
humanize('author_id', capitalize: false) # => "author"
humanize('_id') # => "Id"
humanize('author_id', keep_id_suffix: true) # => "Author id"
如果“SSL”被定义为缩略词
humanize('ssl_error') # => "SSL error"
源代码:显示 | 在 GitHub 上
# File activesupport/lib/active_support/inflector/methods.rb, line 135 def humanize(lower_case_and_underscored_word, capitalize: true, keep_id_suffix: false) result = lower_case_and_underscored_word.to_s.dup inflections.humans.each { |(rule, replacement)| break if result.sub!(rule, replacement) } result.tr!("_", " ") result.lstrip! if !keep_id_suffix && lower_case_and_underscored_word&.end_with?("_id") result.delete_suffix!(" id") end result.gsub!(/([a-z\d]+)/i) do |match| match.downcase! inflections.acronyms[match] || match end if capitalize result.sub!(/\A\w/) do |match| match.upcase! match end end result end
inflections(locale = :en) 链接
生成 Inflector::Inflections
的单例实例,以便您可以指定其他变格规则。如果传递了可选的语言环境,则可以指定其他语言的规则。如果未指定,则默认为:en
。仅提供英语的规则。
ActiveSupport::Inflector.inflections(:en) do |inflect|
inflect.uncountable 'rails'
end
源代码:显示 | 在 GitHub 上
# File activesupport/lib/active_support/inflector/inflections.rb, line 265 def inflections(locale = :en) if block_given? yield Inflections.instance(locale) else Inflections.instance_or_fallback(locale) end end
ordinal(number) 链接
返回应添加到数字后面的后缀,以表示在有序序列中的位置,例如第 1、第 2、第 3、第 4。
ordinal(1) # => "st"
ordinal(2) # => "nd"
ordinal(1002) # => "nd"
ordinal(1003) # => "rd"
ordinal(-11) # => "th"
ordinal(-1021) # => "st"
源代码:显示 | 在 GitHub 上
# File activesupport/lib/active_support/inflector/methods.rb, line 334 def ordinal(number) I18n.translate("number.nth.ordinals", number: number) end
ordinalize(number) 链接
将数字转换为序数字符串,用于表示在有序序列中的位置,例如第 1、第 2、第 3、第 4。
ordinalize(1) # => "1st"
ordinalize(2) # => "2nd"
ordinalize(1002) # => "1002nd"
ordinalize(1003) # => "1003rd"
ordinalize(-11) # => "-11th"
ordinalize(-1021) # => "-1021st"
源代码:显示 | 在 GitHub 上
# File activesupport/lib/active_support/inflector/methods.rb, line 347 def ordinalize(number) I18n.translate("number.nth.ordinalized", number: number) end
parameterize(string, separator: "-", preserve_case: false, locale: nil) 链接
替换字符串中的特殊字符,使其可作为“漂亮”URL 的一部分使用。
parameterize("Donald E. Knuth") # => "donald-e-knuth"
parameterize("^très|Jolie-- ") # => "tres-jolie"
要使用自定义分隔符,请覆盖separator
参数。
parameterize("Donald E. Knuth", separator: '_') # => "donald_e_knuth"
parameterize("^très|Jolie__ ", separator: '_') # => "tres_jolie"
要保留字符串中字符的大小写,请使用preserve_case
参数。
parameterize("Donald E. Knuth", preserve_case: true) # => "Donald-E-Knuth"
parameterize("^très|Jolie-- ", preserve_case: true) # => "tres-Jolie"
它保留连字符和下划线,除非它们用作分隔符
parameterize("^très|Jolie__ ") # => "tres-jolie__"
parameterize("^très|Jolie-- ", separator: "_") # => "tres_jolie--"
parameterize("^très_Jolie-- ", separator: ".") # => "tres_jolie--"
如果指定了可选参数locale
,则该词将被参数化为该语言的词。默认情况下,此参数设置为nil
,它将使用配置的I18n.locale
。
源代码:显示 | 在 GitHub 上
# File activesupport/lib/active_support/inflector/transliterate.rb, line 123 def parameterize(string, separator: "-", preserve_case: false, locale: nil) # Replace accented chars with their ASCII equivalents. parameterized_string = transliterate(string, locale: locale) # Turn unwanted chars into the separator. parameterized_string.gsub!(/[^a-z0-9\-_]+/i, separator) unless separator.nil? || separator.empty? if separator == "-" re_duplicate_separator = /-{2,}/ re_leading_trailing_separator = /^-|-$/i else re_sep = Regexp.escape(separator) re_duplicate_separator = /#{re_sep}{2,}/ re_leading_trailing_separator = /^#{re_sep}|#{re_sep}$/i end # No more than one of the separator in a row. parameterized_string.gsub!(re_duplicate_separator, separator) # Remove leading/trailing separator. parameterized_string.gsub!(re_leading_trailing_separator, "") end parameterized_string.downcase! unless preserve_case parameterized_string end
pluralize(word, locale = :en) 链接
返回字符串中单词的复数形式。
如果传递了可选的locale
参数,则该词将使用为该语言定义的规则进行复数化。默认情况下,此参数设置为:en
。
pluralize('post') # => "posts"
pluralize('octopus') # => "octopi"
pluralize('sheep') # => "sheep"
pluralize('words') # => "words"
pluralize('CamelOctopus') # => "CamelOctopi"
pluralize('ley', :es) # => "leyes"
源代码:显示 | 在 GitHub 上
# File activesupport/lib/active_support/inflector/methods.rb, line 33 def pluralize(word, locale = :en) apply_inflections(word, inflections(locale).plurals, locale) end
safe_constantize(camel_cased_word) 链接
尝试查找与参数字符串中指定名称相同的常量。
safe_constantize('Module') # => Module
safe_constantize('Foo::Bar') # => Foo::Bar
无论名称是否以“::”开头,都假定它是顶级常量的名称。不考虑任何词法上下文
C = 'outside'
module M
C = 'inside'
C # => 'inside'
safe_constantize('C') # => 'outside', same as ::C
end
当名称不是 CamelCase 或常量(或其一部分)未知时,将返回nil
。
safe_constantize('blargle') # => nil
safe_constantize('UnknownModule') # => nil
safe_constantize('UnknownModule::Foo::Bar') # => nil
来源:显示 | 在 GitHub 上
# File activesupport/lib/active_support/inflector/methods.rb, line 315 def safe_constantize(camel_cased_word) constantize(camel_cased_word) rescue NameError => e raise if e.name && !(camel_cased_word.to_s.split("::").include?(e.name.to_s) || e.name.to_s == camel_cased_word.to_s) rescue LoadError => e message = e.respond_to?(:original_message) ? e.original_message : e.message raise unless /Unable to autoload constant #{const_regexp(camel_cased_word)}/.match?(message) end
singularize(word, locale = :en) 链接
是 pluralize
的反操作,返回字符串中单词的单数形式。
如果传递了可选的 locale
参数,则单词将使用为该语言定义的规则进行单数化。默认情况下,此参数设置为 :en
。
singularize('posts') # => "post"
singularize('octopi') # => "octopus"
singularize('sheep') # => "sheep"
singularize('word') # => "word"
singularize('CamelOctopi') # => "CamelOctopus"
singularize('leyes', :es) # => "ley"
来源:显示 | 在 GitHub 上
# File activesupport/lib/active_support/inflector/methods.rb, line 50 def singularize(word, locale = :en) apply_inflections(word, inflections(locale).singulars, locale) end
tableize(class_name) 链接
创建表名,类似 Rails 为模型创建表名的方式。此方法使用字符串中最后一个单词的 pluralize
方法。
tableize('RawScaledScorer') # => "raw_scaled_scorers"
tableize('ham_and_egg') # => "ham_and_eggs"
tableize('fancyCategory') # => "fancy_categories"
来源:显示 | 在 GitHub 上
# File activesupport/lib/active_support/inflector/methods.rb, line 204 def tableize(class_name) pluralize(underscore(class_name)) end
titleize(word, keep_id_suffix: false) 链接
将所有单词首字母大写,并替换字符串中的一些字符,以创建更美观的标题。titleize
用于创建漂亮的输出,不会在 Rails 内部使用。
可以通过将可选参数 keep_id_suffix
设置为 true 来保留并大写结尾的 “_id”、"Id" 等。默认情况下,此参数为 false。
titleize('man from the boondocks') # => "Man From The Boondocks"
titleize('x-men: the last stand') # => "X Men: The Last Stand"
titleize('TheManWithoutAPast') # => "The Man Without A Past"
titleize('raiders_of_the_lost_ark') # => "Raiders Of The Lost Ark"
titleize('string_ending_with_id', keep_id_suffix: true) # => "String Ending With Id"
来源:显示 | 在 GitHub 上
# File activesupport/lib/active_support/inflector/methods.rb, line 192 def titleize(word, keep_id_suffix: false) humanize(underscore(word), keep_id_suffix: keep_id_suffix).gsub(/\b(?<!\w['’`()])[a-z]/) do |match| match.capitalize end end
transliterate(string, replacement = "?", locale: nil) 链接
用 ASCII 近似值替换非 ASCII 字符,如果不存在近似值,则用替换字符,默认为 “?”。
transliterate('Ærøskøbing')
# => "AEroskobing"
为西方/拉丁字符提供默认近似值,例如,"ø"、"ñ"、"é"、"ß" 等。
此方法支持国际化,因此您可以为区域设置设置自定义近似值。例如,这对于将德语的 "ü" 和 "ö" 转写为 "ue" 和 "oe" 很有用,或者为将俄语转写为 ASCII 添加支持。
为了使自定义转写可用,您必须将它们设置为 i18n.transliterate.rule
国际化键。
# Store the transliterations in locales/de.yml
i18n:
transliterate:
rule:
ü: "ue"
ö: "oe"
# Or set them using Ruby
I18n.backend.store_translations(:de, i18n: {
transliterate: {
rule: {
'ü' => 'ue',
'ö' => 'oe'
}
}
})
i18n.transliterate.rule
的值可以是简单的 Hash
,它将字符映射到 ASCII 近似值,如上所示,或者,对于更复杂的要求,可以使用 Proc。
I18n.backend.store_translations(:de, i18n: {
transliterate: {
rule: ->(string) { MyTransliterator.transliterate(string) }
}
})
现在,您可以为每个区域设置不同的转写。
transliterate('Jürgen', locale: :en)
# => "Jurgen"
transliterate('Jürgen', locale: :de)
# => "Juergen"
转写仅限于 UTF-8、US-ASCII 和 GB18030 字符串。其他编码将引发 ArgumentError。
来源:显示 | 在 GitHub 上
# File activesupport/lib/active_support/inflector/transliterate.rb, line 64 def transliterate(string, replacement = "?", locale: nil) raise ArgumentError, "Can only transliterate strings. Received #{string.class.name}" unless string.is_a?(String) raise ArgumentError, "Cannot transliterate strings with #{string.encoding} encoding" unless ALLOWED_ENCODINGS_FOR_TRANSLITERATE.include?(string.encoding) return string.dup if string.ascii_only? string = string.dup if string.frozen? input_encoding = string.encoding # US-ASCII is a subset of UTF-8 so we'll force encoding as UTF-8 if # US-ASCII is given. This way we can let tidy_bytes handle the string # in the same way as we do for UTF-8 string.force_encoding(Encoding::UTF_8) if string.encoding == Encoding::US_ASCII # GB18030 is Unicode compatible but is not a direct mapping so needs to be # transcoded. Using invalid/undef :replace will result in loss of data in # the event of invalid characters, but since tidy_bytes will replace # invalid/undef with a "?" we're safe to do the same beforehand string.encode!(Encoding::UTF_8, invalid: :replace, undef: :replace) if string.encoding == Encoding::GB18030 transliterated = I18n.transliterate( ActiveSupport::Multibyte::Unicode.tidy_bytes(string).unicode_normalize(:nfc), replacement: replacement, locale: locale ) # Restore the string encoding of the input if it was not UTF-8. # Apply invalid/undef :replace as tidy_bytes does transliterated.encode!(input_encoding, invalid: :replace, undef: :replace) if input_encoding != transliterated.encoding transliterated end
underscore(camel_cased_word) 链接
将字符串中的表达式转换为带下划线的小写形式。
将 "::" 更改为 "/",将命名空间转换为路径。
underscore('ActiveModel') # => "active_model"
underscore('ActiveModel::Errors') # => "active_model/errors"
一般来说,您可以将 underscore
视为 camelize
的反操作,尽管有些情况下并不完全相同。
camelize(underscore('SSLError')) # => "SslError"
来源:显示 | 在 GitHub 上
# File activesupport/lib/active_support/inflector/methods.rb, line 99 def underscore(camel_cased_word) return camel_cased_word.to_s.dup unless /[A-Z-]|::/.match?(camel_cased_word) word = camel_cased_word.to_s.gsub("::", "/") word.gsub!(inflections.acronyms_underscore_regex) { "#{$1 && '_' }#{$2.downcase}" } word.gsub!(/(?<=[A-Z])(?=[A-Z][a-z])|(?<=[a-z\d])(?=[A-Z])/, "_") word.tr!("-", "_") word.downcase! word end
upcase_first(string) 链接
将字符串中第一个字符转换为大写。
upcase_first('what a Lovely Day') # => "What a Lovely Day"
upcase_first('w') # => "W"
upcase_first('') # => ""
来源:显示 | 在 GitHub 上
# File activesupport/lib/active_support/inflector/methods.rb, line 166 def upcase_first(string) string.length > 0 ? string[0].upcase.concat(string[1..-1]) : +"" end