Spec-Zone.ru › Ruby on Rails 5.2

модуль ActiveSupport::Inflector

Класс Inflector преобразует слова от единственного к множественному числу, имена классов в имена таблиц, имена модульных классов в имена без модулей и имена классов в внешние ключи. Стандартные склонения для множественного, единственного числа и несчётных слов хранятся в inflections.rb.

Команда разработчиков Rails заявила, что исправления для библиотеки склонений не принимаются, чтобы избежать разрыва совместимости с устаревшими приложениями, которые могут полагаться на неправильные склонения. Если вы обнаружите неверное склонение, необходимое для вашего приложения, или захотите определить правила для языков помимо английского, пожалуйста, исправьте или добавьте их самостоятельно (объяснено ниже).

Общедоступные методы экземпляра

camelize(term, uppercase_first_letter = true) Показать исходный код
# File activesupport/lib/active_support/inflector/methods.rb, line 69
def camelize(term, uppercase_first_letter = true)
  string = term.to_s
  if uppercase_first_letter
    string = string.sub(/^[a-z\d]*/) { |match| inflections.acronyms[match] || match.capitalize }
  else
    string = string.sub(inflections.acronyms_camelize_regex) { |match| match.downcase }
  end
  string.gsub!(/(?:_|(\/))([a-z\d]*)/i) { "#{$1}#{inflections.acronyms[$2] || $2.capitalize}" }
  string.gsub!("/".freeze, "::".freeze)
  string
end

Преобразует строки в ВерхнийCamelCase. Если параметр 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"
classify(table_name) Показать исходный код
# File activesupport/lib/active_support/inflector/methods.rb, line 201
def classify(table_name)
  # strip out any leading schema name
  camelize(singularize(table_name.to_s.sub(/.*\./, "".freeze)))
end

Создаёт имя класса из имени таблицы в множественном числе, как это делает Rails для имён таблиц и моделей. Обратите внимание, что это возвращает строку, а не Класс (Чтобы преобразовать в фактический класс, выполните classify с constantize).

classify('ham_and_eggs') # => "HamAndEgg"
classify('posts')        # => "Post"

Имена в единственном числе не обрабатываются корректно:

classify('calculus')     # => "Calculus"
constantize(camel_cased_word) Показать исходный код
# File activesupport/lib/active_support/inflector/methods.rb, line 272
def constantize(camel_cased_word)
  names = camel_cased_word.split("::".freeze)

  # Trigger a built-in NameError exception including the ill-formed constant in the message.
  Object.const_get(camel_cased_word) if names.empty?

  # Remove the first blank element in case of '::ClassName' notation.
  names.shift if names.size > 1 && names.first.empty?

  names.inject(Object) do |constant, name|
    if constant == Object
      constant.const_get(name)
    else
      candidate = constant.const_get(name)
      next candidate if constant.const_defined?(name, false)
      next candidate unless Object.const_defined?(name)

      # Go down the ancestors to check if it is owned directly. The check
      # stops when we reach Object or the end of ancestors tree.
      constant = constant.ancestors.inject(constant) do |const, ancestor|
        break const    if ancestor == Object
        break ancestor if ancestor.const_defined?(name, false)
        const
      end

      # owner is in Object, so raise
      constant.const_get(name, false)
    end
  end
end

Пытается найти константу с именем, указанным в строке-аргументе.

constantize('Module')   # => Module
constantize('Foo::Bar') # => Foo::Bar

Имя предполагается как имя константы верхнего уровня, независимо от того, начинается ли оно с «::» или нет. Не учитывается лексический контекст:

C = 'outside'
module M
  C = 'inside'
  C                # => 'inside'
  constantize('C') # => 'outside', same as ::C
end

NameError генерируется, когда имя не соответствует CamelCase или константа неизвестна.

dasherize(underscored_word) Показать исходный код
# File activesupport/lib/active_support/inflector/methods.rb, line 209
def dasherize(underscored_word)
  underscored_word.tr("_".freeze, "-".freeze)
end

Заменяет подчёркивания на дефисы в строке.

dasherize('puni_puni') # => "puni-puni"
deconstantize(path) Показать исходный код
# File activesupport/lib/active_support/inflector/methods.rb, line 239
def deconstantize(path)
  path.to_s[0, path.rindex("::") || 0] # implementation based on the one in facets' Module#spacename
end

Удаляет сегмент справа от выражения константы в строке.

deconstantize('Net::HTTP')   # => "Net"
deconstantize('::Net::HTTP') # => "::Net"
deconstantize('String')      # => ""
deconstantize('::String')    # => ""
deconstantize('')            # => ""

См. также demodulize.

demodulize(path) Показать исходный код
# File activesupport/lib/active_support/inflector/methods.rb, line 221
def demodulize(path)
  path = path.to_s
  if i = path.rindex("::")
    path[(i + 2)..-1]
  else
    path
  end
end

Удаляет часть модуля из выражения в строке.

demodulize('ActiveSupport::Inflector::Inflections') # => "Inflections"
demodulize('Inflections')                           # => "Inflections"
demodulize('::Inflections')                         # => "Inflections"
demodulize('')                                      # => ""

См. также deconstantize.

foreign_key(class_name, separate_class_name_and_id_with_underscore = true) Показать исходный код
# File activesupport/lib/active_support/inflector/methods.rb, line 250
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

Создаёт имя внешнего ключа из имени класса. separate_class_name_and_id_with_underscore устанавливает, следует ли методу вставлять «_» между именем и «id».

foreign_key('Message')        # => "message_id"
foreign_key('Message', false) # => "messageid"
foreign_key('Admin::Post')    # => "post_id"
humanize(lower_case_and_underscored_word, capitalize: true, keep_id_suffix: false) Показать исходный код
# File activesupport/lib/active_support/inflector/methods.rb, line 129
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.sub!(/\A_+/, "".freeze)
  unless keep_id_suffix
    result.sub!(/_id\z/, "".freeze)
  end
  result.tr!("_".freeze, " ".freeze)

  result.gsub!(/([a-z\d]*)/i) do |match|
    "#{inflections.acronyms[match.downcase] || match.downcase}"
  end

  if capitalize
    result.sub!(/\A\w/) { |match| match.upcase }
  end

  result
end

Изменяет имя атрибута для отображения пользователю.

Конкретно, выполняет следующие преобразования:

  • Применяет правила человекообразной инфлексии к аргументу.

  • Удаляет ведущие подчёркивания, если они есть.

  • Удаляет суффикс «_id», если он присутствует.

  • Заменяет подчёркивания пробелами, если они есть.

  • Преобразует все слова в нижний регистр, за исключением аббревиатур.

  • Преобразует первое слово в верхний регистр.

Регистр первого слова можно отключить, установив опцию :capitalize в false (по умолчанию true).

Завершающий «_id» можно сохранить и преобразовать в верхний регистр, установив необязательный параметр keep_id_suffix в true (по умолчанию 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"
inflections(locale = :en) { |instance| ... } Показать исходный код
# File activesupport/lib/active_support/inflector/inflections.rb, line 252
def inflections(locale = :en)
  if block_given?
    yield Inflections.instance(locale)
  else
    Inflections.instance(locale)
  end
end

Возвращает экземпляр Inflector::Inflections для указания дополнительных правил инфлексии. Если передан необязательный параметр locale, правила для других языков можно указать. Если не указано, по умолчанию :en. Предоставляются только правила для английского языка.

ActiveSupport::Inflector.inflections(:en) do |inflect|
  inflect.uncountable 'rails'
end
ordinal(number) Показать исходный код
# File activesupport/lib/active_support/inflector/methods.rb, line 343
def ordinal(number)
  abs_number = number.to_i.abs

  if (11..13).include?(abs_number % 100)
    "th"
  else
    case abs_number % 10
    when 1; "st"
    when 2; "nd"
    when 3; "rd"
    else    "th"
    end
  end
end

Возвращает суффикс, который следует добавить к числу, чтобы указать его позицию в упорядоченной последовательности, например 1-е, 2-е, 3-е, 4-е.

ordinal(1)     # => "st"
ordinal(2)     # => "nd"
ordinal(1002)  # => "nd"
ordinal(1003)  # => "rd"
ordinal(-11)   # => "th"
ordinal(-1021) # => "st"
ordinalize(number) Показать исходный код
# File activesupport/lib/active_support/inflector/methods.rb, line 367
def ordinalize(number)
  "#{number}#{ordinal(number)}"
end

Преобразует число в строку ординала, используемую для обозначения позиции в упорядоченной последовательности, например 1-е, 2-е, 3-е, 4-е.

ordinalize(1)     # => "1st"
ordinalize(2)     # => "2nd"
ordinalize(1002)  # => "1002nd"
ordinalize(1003)  # => "1003rd"
ordinalize(-11)   # => "-11th"
ordinalize(-1021) # => "-1021st"
parameterize(string, separator: "-", preserve_case: false) Показать исходный код
# File activesupport/lib/active_support/inflector/transliterate.rb, line 92
def parameterize(string, separator: "-", preserve_case: false)
  # Replace accented chars with their ASCII equivalents.
  parameterized_string = transliterate(string)

  # Turn unwanted chars into the separator.
  parameterized_string.gsub!(/[^a-z0-9\-_]+/i, separator)

  unless separator.nil? || separator.empty?
    if separator == "-".freeze
      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, "".freeze)
  end

  parameterized_string.downcase! unless preserve_case
  parameterized_string
end

Заменяет специальные символы в строке, чтобы она могла быть использована в качестве части «красивого» 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--"
pluralize(word, locale = :en) Показать исходный код
# File activesupport/lib/active_support/inflector/methods.rb, line 32
def pluralize(word, locale = :en)
  apply_inflections(word, inflections(locale).plurals, locale)
end

Возвращает форму слова во множественном числе.

Если передан необязательный параметр locale, слово будет приведено к форме множественного числа с использованием правил, определённых для этого языка. По умолчанию этот параметр равен :en.

pluralize('post')             # => "posts"
pluralize('octopus')          # => "octopi"
pluralize('sheep')            # => "sheep"
pluralize('words')            # => "words"
pluralize('CamelOctopus')     # => "CamelOctopi"
pluralize('ley', :es)         # => "leyes"
safe_constantize(camel_cased_word) Показать исходный код
# File activesupport/lib/active_support/inflector/methods.rb, line 325
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 ArgumentError => e
  raise unless /not missing constant #{const_regexp(camel_cased_word)}!$/.match?(e.message)
end

Пытается найти константу с именем, указанным в строке-аргументе.

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, когда имя не соответствует CamelCase или константа (или её часть) неизвестна.

safe_constantize('blargle')                  # => nil
safe_constantize('UnknownModule')            # => nil
safe_constantize('UnknownModule::Foo::Bar')  # => nil
singularize(word, locale = :en) Показать исходный код
# File activesupport/lib/active_support/inflector/methods.rb, line 49
def singularize(word, locale = :en)
  apply_inflections(word, inflections(locale).singulars, locale)
end

Обратное к pluralize, возвращает форму слова в единственном числе.

Если передан необязательный параметр locale, слово будет приведено к форме единственного числа с использованием правил, определённых для этого языка. По умолчанию этот параметр равен :en.

singularize('posts')            # => "post"
singularize('octopi')           # => "octopus"
singularize('sheep')            # => "sheep"
singularize('word')             # => "word"
singularize('CamelOctopi')      # => "CamelOctopus"
singularize('leyes', :es)       # => "ley"
tableize(class_name) Показать исходный код
# File activesupport/lib/active_support/inflector/methods.rb, line 187
def tableize(class_name)
  pluralize(underscore(class_name))
end

Создаёт имя таблицы, как это делает Rails для моделей в названиях таблиц. Этот метод использует метод pluralize для последнего слова в строке.

tableize('RawScaledScorer') # => "raw_scaled_scorers"
tableize('ham_and_egg')     # => "ham_and_eggs"
tableize('fancyCategory')   # => "fancy_categories"
titleize(word, keep_id_suffix: false) Показать исходный код
# File activesupport/lib/active_support/inflector/methods.rb, line 175
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

Преобразует все слова в верхний регистр и заменяет некоторые символы в строке, чтобы создать более привлекательный заголовок. titleize предназначен для создания красивого вывода. Он не используется во внутренних компонентах Rails.

Суффикс «_id», «Id» и т. д. можно сохранить и привести к верхнему регистру, установив необязательный параметр keep_id_suffix в значение true. По умолчанию этот параметр имеет значение false.

titleize также является алиасом для titlecase.

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"
transliterate(string, replacement = "?".freeze) Показать исходный код
# File activesupport/lib/active_support/inflector/transliterate.rb, line 61
def transliterate(string, replacement = "?".freeze)
  raise ArgumentError, "Can only transliterate strings. Received #{string.class.name}" unless string.is_a?(String)

  I18n.transliterate(
    ActiveSupport::Multibyte::Unicode.normalize(
      ActiveSupport::Multibyte::Unicode.tidy_bytes(string), :c),
    replacement: replacement)
end

Заменяет символы, не являющиеся ASCII, на их приближенные ASCII-аналоги или, если такового нет, на символ замены, по умолчанию равный «?».

transliterate('Ærøskøbing')
# => "AEroskobing"

Предоставляются приближенные аналоги для символов Западной/Латинской письменности, например, «ø», «ñ», «é», «ß» и т. д.

Этот метод учитывает I18n, поэтому вы можете настроить собственные приближения для локалей. Это может быть полезно, например, для транслитерации немецких «ü» и «ö» в «ue» и «oe» или для добавления поддержки транслитерации русского языка в ASCII.

Чтобы ваши пользовательские транслитерации были доступны, необходимо установить их в виде ключа i18n.transliterate.rule в i18n:

# 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 может быть простым словарям, который сопоставляет символы с их ASCII-аналогами, как показано выше, или, для более сложных требований, функцией:

I18n.backend.store_translations(:de, i18n: {
  transliterate: {
    rule: ->(string) { MyTransliterator.transliterate(string) }
  }
})

Теперь вы можете иметь разные транслитерации для каждой локали:

I18n.locale = :en
transliterate('Jürgen')
# => "Jurgen"

I18n.locale = :de
transliterate('Jürgen')
# => "Juergen"
underscore(camel_cased_word) Показать исходный код
# File activesupport/lib/active_support/inflector/methods.rb, line 92
def underscore(camel_cased_word)
  return camel_cased_word unless /[A-Z-]|::/.match?(camel_cased_word)
  word = camel_cased_word.to_s.gsub("::".freeze, "/".freeze)
  word.gsub!(inflections.acronyms_underscore_regex) { "#{$1 && '_'.freeze }#{$2.downcase}" }
  word.gsub!(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2'.freeze)
  word.gsub!(/([a-z\d])([A-Z])/, '\1_\2'.freeze)
  word.tr!("-".freeze, "_".freeze)
  word.downcase!
  word
end

Преобразует выражение в строке в нижний регистр с подчёркиванием.

Заменяет «::» на «/» для преобразования пространств имён в пути.

underscore('ActiveModel')         # => "active_model"
underscore('ActiveModel::Errors') # => "active_model/errors"

В качестве правила можно считать, что underscore является обратной функцией camelize, хотя существуют случаи, когда это не так:

camelize(underscore('SSLError'))  # => "SslError"
upcase_first(string) Показать исходный код
# File activesupport/lib/active_support/inflector/methods.rb, line 156
def upcase_first(string)
  string.length > 0 ? string[0].upcase.concat(string[1..-1]) : ""
end

Преобразует только первый символ в верхний регистр.

upcase_first('what a Lovely Day') # => "What a Lovely Day"
upcase_first('w')                 # => "W"
upcase_first('')                  # => ""

© 2004–2018 David Heinemeier Hansson
Licensed under the MIT License.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API