Active Support 變形器
Inflector
將單數詞彙轉換為複數、類別名稱轉換為表格名稱、模組化類別名稱轉換為非模組化名稱,以及類別名稱轉換為外鍵。複數化、單數化和不可數名詞的預設變形規則保存在 inflections.rb 中。
Rails 核心團隊已聲明,不會接受針對變形器函式庫的修補程式,以避免破壞可能依賴錯誤變形規則的舊版應用程式。如果您發現不正確的變形規則,且您的應用程式需要它,或者您希望定義英語以外語言的規則,請自行更正或新增它們(如下所述)。
- 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 將表格名稱轉換為模型一樣。請注意,這會傳回一個字串,而不是一個 Class
。(要轉換為實際的類別,請在 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
當名稱不是駝峰式命名法或常數未知時,會引發 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) 連結
從字串中的常數表達式移除最右邊的區段。另請參閱 demodulize
。
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) 連結
從字串中的表達式移除模組部分。另請參閱 deconstantize
。
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)來關閉第一個單詞的大寫。
可以通過將`:capitalize`選項設置為false(默認為true)來關閉首字母大寫的功能。
可以透過將可選參數 keep_id_suffix
設定為 true(預設為 false)來保留尾部的「_id」並將其大寫。
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) 連結
傳回應新增到數字的後綴,以表示在有序序列中的位置,例如 1st、2nd、3rd、4th。來源:顯示 | 在 GitHub 上
ordinal(1) # => "st"
ordinal(2) # => "nd"
ordinal(1002) # => "nd"
ordinal(1003) # => "rd"
ordinal(-11) # => "th"
ordinal(-1021) # => "st"
傳回應該加到數字後面的後綴,用來表示在有序序列中的位置,例如 1st、2nd、3rd、4th。
# File activesupport/lib/active_support/inflector/methods.rb, line 334 def ordinal(number) I18n.translate("number.nth.ordinals", number: number) end
ordinalize(number) 連結
將數字轉換為序數字串,用於表示在有序序列中的位置,例如 1st、2nd、3rd、4th。
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) 連結
替換字串中的特殊字元,以便其可以用作「漂亮」網址的一部分。要使用自定義分隔符號,請覆寫 separator
參數。要保留字串中字元的大小寫,請使用 preserve_case
參數。它會保留破折號和底線,除非它們被用作分隔符號。如果指定了可選參數 locale
,則該單詞將被參數化為該語言的單詞。預設情況下,此參數設定為 nil
,它將使用已設定的 I18n.locale
。
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
。
如果傳入一個可選的 `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
當名稱不是駝峰式命名法或常數(或其一部分)未知時,會傳回 nil
。來源:顯示 | 在 GitHub 上
safe_constantize('blargle') # => nil
safe_constantize('UnknownModule') # => nil
safe_constantize('UnknownModule::Foo::Bar') # => nil
當名稱不是駝峰式命名或常數(或其中一部分)未知時,將會回傳 `nil`。
# 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
。
如果傳入一個可選的 `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"
提供西方/拉丁字元的預設近似值,例如「ø」、「ñ」、「é」、「ß」等。
此方法支援國際化 (I18n),因此您可以針對特定語系設定自訂近似值。例如,這可以用於將德語的「ü」和「ö」音譯為「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