Correct vendoring of inflector
This commit is contained in:
parent
49dba174ad
commit
8ef816d012
6 changed files with 278 additions and 425 deletions
7
lib/inflector.rb
Normal file
7
lib/inflector.rb
Normal file
|
@ -0,0 +1,7 @@
|
|||
# Library namespace
|
||||
module Inflector
|
||||
end
|
||||
|
||||
require 'inflector/inflections'
|
||||
require 'inflector/defaults'
|
||||
require 'inflector/methods'
|
62
lib/inflector/defaults.rb
Normal file
62
lib/inflector/defaults.rb
Normal file
|
@ -0,0 +1,62 @@
|
|||
module Inflector
|
||||
Inflector::Inflections.instance.instance_eval do
|
||||
plural(/$/, 's')
|
||||
plural(/s$/i, 's')
|
||||
plural(/us$/i, 'i')
|
||||
plural(/(ax|test)is$/i, '\1es')
|
||||
plural(/(octop|vir)us$/i, '\1i')
|
||||
plural(/(octop|vir)i$/i, '\1i')
|
||||
plural(/(alias|status)$/i, '\1es')
|
||||
plural(/(bu)s$/i, '\1ses')
|
||||
plural(/(buffal|tomat)o$/i, '\1oes')
|
||||
plural(/([ti])um$/i, '\1a')
|
||||
plural(/([ti])a$/i, '\1a')
|
||||
plural(/sis$/i, 'ses')
|
||||
plural(/(?:([^f])fe|([lr])f)$/i, '\1\2ves')
|
||||
plural(/(hive)$/i, '\1s')
|
||||
plural(/([^aeiouy]|qu)y$/i, '\1ies')
|
||||
plural(/(x|ch|ss|sh)$/i, '\1es')
|
||||
plural(/(matr|vert|ind)(?:ix|ex)$/i, '\1ices')
|
||||
plural(/([m|l])ouse$/i, '\1ice')
|
||||
plural(/([m|l])ice$/i, '\1ice')
|
||||
plural(/^(ox)$/i, '\1en')
|
||||
plural(/^(oxen)$/i, '\1')
|
||||
plural(/(quiz)$/i, '\1zes')
|
||||
|
||||
singular(/s$/i, '')
|
||||
singular(/i$/i, 'us')
|
||||
singular(/(n)ews$/i, '\1ews')
|
||||
singular(/([ti])a$/i, '\1um')
|
||||
singular(/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i, '\1\2sis')
|
||||
singular(/(^analy)ses$/i, '\1sis')
|
||||
singular(/([^f])ves$/i, '\1fe')
|
||||
singular(/(hive)s$/i, '\1')
|
||||
singular(/(tive)s$/i, '\1')
|
||||
singular(/([lr])ves$/i, '\1f')
|
||||
singular(/([^aeiouy]|qu)ies$/i, '\1y')
|
||||
singular(/(s)eries$/i, '\1eries')
|
||||
singular(/(m)ovies$/i, '\1ovie')
|
||||
singular(/(x|ch|ss|sh)es$/i, '\1')
|
||||
singular(/([m|l])ice$/i, '\1ouse')
|
||||
singular(/(bus)es$/i, '\1')
|
||||
singular(/(o)es$/i, '\1')
|
||||
singular(/(shoe)s$/i, '\1')
|
||||
singular(/(cris|ax|test)es$/i, '\1is')
|
||||
singular(/(octop|vir)i$/i, '\1us')
|
||||
singular(/(alias|status)es$/i, '\1')
|
||||
singular(/^(ox)en/i, '\1')
|
||||
singular(/(vert|ind)ices$/i, '\1ex')
|
||||
singular(/(matr)ices$/i, '\1ix')
|
||||
singular(/(quiz)zes$/i, '\1')
|
||||
singular(/(database)s$/i, '\1')
|
||||
|
||||
irregular('person', 'people')
|
||||
irregular('man', 'men')
|
||||
irregular('child', 'children')
|
||||
irregular('sex', 'sexes')
|
||||
irregular('move', 'moves')
|
||||
irregular('cow', 'kine')
|
||||
|
||||
uncountable(%w(grass equipment information rice money species series fish sheep jeans))
|
||||
end
|
||||
end
|
209
lib/inflector/inflections.rb
Normal file
209
lib/inflector/inflections.rb
Normal file
|
@ -0,0 +1,209 @@
|
|||
module Inflector
|
||||
# A singleton instance of this class is yielded by Inflector.inflections, which can then be used to specify additional
|
||||
# inflection rules. Examples:
|
||||
#
|
||||
# Inflector.inflections do |inflect|
|
||||
# inflect.plural /^(ox)$/i, '\1\2en'
|
||||
# inflect.singular /^(ox)en/i, '\1'
|
||||
#
|
||||
# inflect.irregular 'octopus', 'octopi'
|
||||
#
|
||||
# inflect.uncountable "equipment"
|
||||
# end
|
||||
#
|
||||
# New rules are added at the top. So in the example above, the irregular rule for octopus will now be the first of the
|
||||
# pluralization and singularization rules that is runs. This guarantees that your rules run before any of the rules that may
|
||||
# already have been loaded.
|
||||
class Inflections
|
||||
def self.instance
|
||||
@__instance__ ||= new
|
||||
end
|
||||
|
||||
attr_reader :plurals, :singulars, :uncountables, :humans
|
||||
|
||||
def initialize
|
||||
@plurals, @singulars, @uncountables, @humans = [], [], [], []
|
||||
end
|
||||
|
||||
# Specifies a new pluralization rule and its replacement. The rule can either be a string or a regular expression.
|
||||
# The replacement should always be a string that may include references to the matched data from the rule.
|
||||
def plural(rule, replacement)
|
||||
@uncountables.delete(rule) if rule.is_a?(String)
|
||||
@uncountables.delete(replacement)
|
||||
@plurals.insert(0, [rule, replacement])
|
||||
end
|
||||
|
||||
# Specifies a new singularization rule and its replacement. The rule can either be a string or a regular expression.
|
||||
# The replacement should always be a string that may include references to the matched data from the rule.
|
||||
def singular(rule, replacement)
|
||||
@uncountables.delete(rule) if rule.is_a?(String)
|
||||
@uncountables.delete(replacement)
|
||||
@singulars.insert(0, [rule, replacement])
|
||||
end
|
||||
|
||||
# Specifies a new irregular that applies to both pluralization and singularization at the same time. This can only be used
|
||||
# for strings, not regular expressions. You simply pass the irregular in singular and plural form.
|
||||
#
|
||||
# Examples:
|
||||
# irregular 'octopus', 'octopi'
|
||||
# irregular 'person', 'people'
|
||||
def irregular(singular, plural)
|
||||
@uncountables.delete(singular)
|
||||
@uncountables.delete(plural)
|
||||
if singular[0,1].upcase == plural[0,1].upcase
|
||||
plural(Regexp.new("(#{singular[0,1]})#{singular[1..-1]}$", "i"), '\1' + plural[1..-1])
|
||||
plural(Regexp.new("(#{plural[0,1]})#{plural[1..-1]}$", "i"), '\1' + plural[1..-1])
|
||||
singular(Regexp.new("(#{plural[0,1]})#{plural[1..-1]}$", "i"), '\1' + singular[1..-1])
|
||||
else
|
||||
plural(Regexp.new("#{singular[0,1].upcase}(?i)#{singular[1..-1]}$"), plural[0,1].upcase + plural[1..-1])
|
||||
plural(Regexp.new("#{singular[0,1].downcase}(?i)#{singular[1..-1]}$"), plural[0,1].downcase + plural[1..-1])
|
||||
plural(Regexp.new("#{plural[0,1].upcase}(?i)#{plural[1..-1]}$"), plural[0,1].upcase + plural[1..-1])
|
||||
plural(Regexp.new("#{plural[0,1].downcase}(?i)#{plural[1..-1]}$"), plural[0,1].downcase + plural[1..-1])
|
||||
singular(Regexp.new("#{plural[0,1].upcase}(?i)#{plural[1..-1]}$"), singular[0,1].upcase + singular[1..-1])
|
||||
singular(Regexp.new("#{plural[0,1].downcase}(?i)#{plural[1..-1]}$"), singular[0,1].downcase + singular[1..-1])
|
||||
end
|
||||
end
|
||||
|
||||
# Add uncountable words that shouldn't be attempted inflected.
|
||||
#
|
||||
# Examples:
|
||||
# uncountable "money"
|
||||
# uncountable "money", "information"
|
||||
# uncountable %w( money information rice )
|
||||
def uncountable(*words)
|
||||
(@uncountables << words).flatten!
|
||||
end
|
||||
|
||||
# Specifies a humanized form of a string by a regular expression rule or by a string mapping.
|
||||
# When using a regular expression based replacement, the normal humanize formatting is called after the replacement.
|
||||
# When a string is used, the human form should be specified as desired (example: 'The name', not 'the_name')
|
||||
#
|
||||
# Examples:
|
||||
# human /_cnt$/i, '\1_count'
|
||||
# human "legacy_col_person_name", "Name"
|
||||
def human(rule, replacement)
|
||||
@humans.insert(0, [rule, replacement])
|
||||
end
|
||||
|
||||
# Clears the loaded inflections within a given scope (default is <tt>:all</tt>).
|
||||
# Give the scope as a symbol of the inflection type, the options are: <tt>:plurals</tt>,
|
||||
# <tt>:singulars</tt>, <tt>:uncountables</tt>, <tt>:humans</tt>.
|
||||
#
|
||||
# Examples:
|
||||
# clear :all
|
||||
# clear :plurals
|
||||
def clear(scope = :all)
|
||||
case scope
|
||||
when :all
|
||||
@plurals, @singulars, @uncountables = [], [], []
|
||||
else
|
||||
instance_variable_set "@#{scope}", []
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Yields a singleton instance of Inflector::Inflections so you can specify additional
|
||||
# inflector rules.
|
||||
#
|
||||
# Example:
|
||||
# Inflector.inflections do |inflect|
|
||||
# inflect.uncountable "rails"
|
||||
# end
|
||||
def inflections
|
||||
if block_given?
|
||||
yield Inflections.instance
|
||||
else
|
||||
Inflections.instance
|
||||
end
|
||||
end
|
||||
|
||||
# Returns the plural form of the word in the string.
|
||||
#
|
||||
# Examples:
|
||||
# "post".pluralize # => "posts"
|
||||
# "octopus".pluralize # => "octopi"
|
||||
# "sheep".pluralize # => "sheep"
|
||||
# "words".pluralize # => "words"
|
||||
# "CamelOctopus".pluralize # => "CamelOctopi"
|
||||
def pluralize(word)
|
||||
result = word.to_s.dup
|
||||
|
||||
if word.empty? || inflections.uncountables.include?(result.downcase)
|
||||
result
|
||||
else
|
||||
inflections.plurals.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
|
||||
result
|
||||
end
|
||||
end
|
||||
|
||||
# The reverse of +pluralize+, returns the singular form of a word in a string.
|
||||
#
|
||||
# Examples:
|
||||
# "posts".singularize # => "post"
|
||||
# "octopi".singularize # => "octopus"
|
||||
# "sheep".singularize # => "sheep"
|
||||
# "word".singularize # => "word"
|
||||
# "CamelOctopi".singularize # => "CamelOctopus"
|
||||
def singularize(word)
|
||||
result = word.to_s.dup
|
||||
|
||||
if inflections.uncountables.any? { |inflection| result =~ /\b(#{inflection})\Z/i }
|
||||
result
|
||||
else
|
||||
inflections.singulars.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
|
||||
result
|
||||
end
|
||||
end
|
||||
|
||||
# Capitalizes the first word and turns underscores into spaces and strips a
|
||||
# trailing "_id", if any. Like +titleize+, this is meant for creating pretty output.
|
||||
#
|
||||
# Examples:
|
||||
# "employee_salary" # => "Employee salary"
|
||||
# "author_id" # => "Author"
|
||||
def humanize(lower_case_and_underscored_word)
|
||||
result = lower_case_and_underscored_word.to_s.dup
|
||||
|
||||
inflections.humans.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
|
||||
result.gsub(/_id$/, "").gsub(/_/, " ").capitalize
|
||||
end
|
||||
|
||||
# Capitalizes all the words and replaces some characters in the string to create
|
||||
# a nicer looking title. +titleize+ is meant for creating pretty output. It is not
|
||||
# used in the Rails internals.
|
||||
#
|
||||
# +titleize+ is also aliased as as +titlecase+.
|
||||
#
|
||||
# Examples:
|
||||
# "man from the boondocks".titleize # => "Man From The Boondocks"
|
||||
# "x-men: the last stand".titleize # => "X Men: The Last Stand"
|
||||
def titleize(word)
|
||||
humanize(underscore(word)).gsub(/\b('?[a-z])/) { $1.capitalize }
|
||||
end
|
||||
|
||||
# Create the name of a table like Rails does for models to table names. This method
|
||||
# uses the +pluralize+ method on the last word in the string.
|
||||
#
|
||||
# Examples
|
||||
# "RawScaledScorer".tableize # => "raw_scaled_scorers"
|
||||
# "egg_and_ham".tableize # => "egg_and_hams"
|
||||
# "fancyCategory".tableize # => "fancy_categories"
|
||||
def tableize(class_name)
|
||||
pluralize(underscore(class_name))
|
||||
end
|
||||
|
||||
# Create a class name from a plural table name like Rails does for table names to models.
|
||||
# Note that this returns a string and not a Class. (To convert to an actual class
|
||||
# follow +classify+ with +constantize+.)
|
||||
#
|
||||
# Examples:
|
||||
# "egg_and_hams".classify # => "EggAndHam"
|
||||
# "posts".classify # => "Post"
|
||||
#
|
||||
# Singular names are not handled correctly:
|
||||
# "business".classify # => "Busines"
|
||||
def classify(table_name)
|
||||
# strip out any leading schema name
|
||||
camelize(singularize(table_name.to_s.sub(/.*\./, '')))
|
||||
end
|
||||
end
|
|
@ -1,425 +0,0 @@
|
|||
# = English Nouns Number Inflection.
|
||||
#
|
||||
# This module provides english singular <-> plural noun inflections.
|
||||
module Inflector
|
||||
|
||||
# Take an underscored name and make it into a camelized name
|
||||
#
|
||||
# @example
|
||||
# "egg_and_hams".classify #=> "EggAndHam"
|
||||
# "enlarged_testes".classify #=> "EnlargedTestis"
|
||||
# "post".classify #=> "Post"
|
||||
#
|
||||
def self.classify(name)
|
||||
words = name.to_s.sub(/.*\./, '').split('_')
|
||||
words[-1] = singularize(words[-1])
|
||||
words.collect { |word| word.capitalize }.join
|
||||
end
|
||||
|
||||
# By default, camelize converts strings to UpperCamelCase.
|
||||
#
|
||||
# camelize will also convert '/' to '::' which is useful for converting paths to namespaces
|
||||
#
|
||||
# @example
|
||||
# "active_record".camelize #=> "ActiveRecord"
|
||||
# "active_record/errors".camelize #=> "ActiveRecord::Errors"
|
||||
#
|
||||
def self.camelize(lower_case_and_underscored_word, *args)
|
||||
lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase }
|
||||
end
|
||||
|
||||
|
||||
# The reverse of +camelize+. Makes an underscored form from the expression in the string.
|
||||
#
|
||||
# Changes '::' to '/' to convert namespaces to paths.
|
||||
#
|
||||
# @example
|
||||
# "ActiveRecord".underscore #=> "active_record"
|
||||
# "ActiveRecord::Errors".underscore #=> active_record/errors
|
||||
#
|
||||
def self.underscore(camel_cased_word)
|
||||
camel_cased_word.to_const_path
|
||||
end
|
||||
|
||||
# Capitalizes the first word and turns underscores into spaces and strips _id.
|
||||
# Like titleize, this is meant for creating pretty output.
|
||||
#
|
||||
# @example
|
||||
# "employee_salary" #=> "Employee salary"
|
||||
# "author_id" #=> "Author"
|
||||
def self.humanize(lower_case_and_underscored_word)
|
||||
lower_case_and_underscored_word.to_s.gsub(/_id$/, '').tr('_', ' ').capitalize
|
||||
end
|
||||
|
||||
# Removes the module part from the expression in the string
|
||||
#
|
||||
# @example
|
||||
# "ActiveRecord::CoreExtensions::String::Inflections".demodulize #=> "Inflections"
|
||||
# "Inflections".demodulize #=> "Inflections"
|
||||
def self.demodulize(class_name_in_module)
|
||||
class_name_in_module.to_s.gsub(/^.*::/, '')
|
||||
end
|
||||
|
||||
# Create the name of a table like Rails does for models to table names. This method
|
||||
# uses the pluralize method on the last word in the string.
|
||||
#
|
||||
# @example
|
||||
# "RawScaledScorer".tableize #=> "raw_scaled_scorers"
|
||||
# "EnlargedTestis".tableize #=> "enlarged_testes"
|
||||
# "egg_and_ham".tableize #=> "egg_and_hams"
|
||||
# "fancyCategory".tableize #=> "fancy_categories"
|
||||
def self.tableize(class_name)
|
||||
words = class_name.to_const_path.tr('/', '_').split('_')
|
||||
words[-1] = pluralize(words[-1])
|
||||
words.join('_')
|
||||
end
|
||||
|
||||
# Creates a foreign key name from a class name.
|
||||
#
|
||||
# @example
|
||||
# "Message".foreign_key #=> "message_id"
|
||||
# "Admin::Post".foreign_key #=> "post_id"
|
||||
def self.foreign_key(class_name, key = "id")
|
||||
underscore(demodulize(class_name.to_s)) << "_" << key.to_s
|
||||
end
|
||||
|
||||
# Constantize tries to find a declared constant with the name specified
|
||||
# in the string. It raises a NameError when the name is not in CamelCase
|
||||
# or is not initialized.
|
||||
#
|
||||
# @example
|
||||
# "Module".constantize #=> Module
|
||||
# "Class".constantize #=> Class
|
||||
def self.constantize(camel_cased_word)
|
||||
unless /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/ =~ camel_cased_word
|
||||
raise NameError, "#{camel_cased_word.inspect} is not a valid constant name!"
|
||||
end
|
||||
|
||||
Object.module_eval("::#{$1}", __FILE__, __LINE__)
|
||||
end
|
||||
end
|
||||
|
||||
@singular_of = {}
|
||||
@plural_of = {}
|
||||
|
||||
@singular_rules = []
|
||||
@plural_rules = []
|
||||
|
||||
class << self
|
||||
# Defines a general inflection exception case.
|
||||
#
|
||||
# ==== Parameters
|
||||
# singular<String>::
|
||||
# singular form of the word
|
||||
# plural<String>::
|
||||
# plural form of the word
|
||||
#
|
||||
# ==== Examples
|
||||
#
|
||||
# Here we define erratum/errata exception case:
|
||||
#
|
||||
# English::Inflect.word "erratum", "errata"
|
||||
#
|
||||
# In case singular and plural forms are the same omit
|
||||
# second argument on call:
|
||||
#
|
||||
# English::Inflect.word 'information'
|
||||
def self.word(singular, plural=nil)
|
||||
plural = singular unless plural
|
||||
singular_word(singular, plural)
|
||||
plural_word(singular, plural)
|
||||
end
|
||||
|
||||
def self.clear(type = :all)
|
||||
if type == :singular || type == :all
|
||||
@singular_of = {}
|
||||
@singular_rules = []
|
||||
@singularization_rules, @singularization_regex = nil, nil
|
||||
end
|
||||
if type == :plural || type == :all
|
||||
@singular_of = {}
|
||||
@singular_rules = []
|
||||
@singularization_rules, @singularization_regex = nil, nil
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# Define a singularization exception.
|
||||
#
|
||||
# ==== Parameters
|
||||
# singular<String>::
|
||||
# singular form of the word
|
||||
# plural<String>::
|
||||
# plural form of the word
|
||||
def self.singular_word(singular, plural)
|
||||
@singular_of[plural] = singular
|
||||
@singular_of[plural.capitalize] = singular.capitalize
|
||||
end
|
||||
|
||||
# Define a pluralization exception.
|
||||
#
|
||||
# ==== Parameters
|
||||
# singular<String>::
|
||||
# singular form of the word
|
||||
# plural<String>::
|
||||
# plural form of the word
|
||||
def self.plural_word(singular, plural)
|
||||
@plural_of[singular] = plural
|
||||
@plural_of[singular.capitalize] = plural.capitalize
|
||||
end
|
||||
|
||||
# Define a general rule.
|
||||
#
|
||||
# ==== Parameters
|
||||
# singular<String>::
|
||||
# ending of the word in singular form
|
||||
# plural<String>::
|
||||
# ending of the word in plural form
|
||||
# whole_word<Boolean>::
|
||||
# for capitalization, since words can be
|
||||
# capitalized (Man => Men) #
|
||||
# ==== Examples
|
||||
# Once the following rule is defined:
|
||||
# English::Inflect.rule 'y', 'ies'
|
||||
#
|
||||
# You can see the following results:
|
||||
# irb> "fly".plural
|
||||
# => flies
|
||||
# irb> "cry".plural
|
||||
# => cries
|
||||
# Define a general rule.
|
||||
|
||||
def self.rule(singular, plural, whole_word = false)
|
||||
singular_rule(singular, plural)
|
||||
plural_rule(singular, plural)
|
||||
word(singular, plural) if whole_word
|
||||
end
|
||||
|
||||
# Define a singularization rule.
|
||||
#
|
||||
# ==== Parameters
|
||||
# singular<String>::
|
||||
# ending of the word in singular form
|
||||
# plural<String>::
|
||||
# ending of the word in plural form
|
||||
#
|
||||
# ==== Examples
|
||||
# Once the following rule is defined:
|
||||
# English::Inflect.singular_rule 'o', 'oes'
|
||||
#
|
||||
# You can see the following results:
|
||||
# irb> "heroes".singular
|
||||
# => hero
|
||||
def self.singular_rule(singular, plural)
|
||||
@singular_rules << [singular, plural]
|
||||
end
|
||||
|
||||
# Define a plurualization rule.
|
||||
#
|
||||
# ==== Parameters
|
||||
# singular<String>::
|
||||
# ending of the word in singular form
|
||||
# plural<String>::
|
||||
# ending of the word in plural form
|
||||
#
|
||||
# ==== Examples
|
||||
# Once the following rule is defined:
|
||||
# English::Inflect.singular_rule 'fe', 'ves'
|
||||
#
|
||||
# You can see the following results:
|
||||
# irb> "wife".plural
|
||||
# => wives
|
||||
def self.plural_rule(singular, plural)
|
||||
@plural_rules << [singular, plural]
|
||||
end
|
||||
|
||||
# Read prepared singularization rules.
|
||||
def self.singularization_rules
|
||||
if defined?(@singularization_regex) && @singularization_regex
|
||||
return [@singularization_regex, @singularization_hash]
|
||||
end
|
||||
# No sorting needed: Regexen match on longest string
|
||||
@singularization_regex = Regexp.new("(" + @singular_rules.map {|s,p| p}.join("|") + ")$", "i")
|
||||
@singularization_hash = Hash[*@singular_rules.flatten].invert
|
||||
[@singularization_regex, @singularization_hash]
|
||||
end
|
||||
|
||||
# Read prepared pluralization rules.
|
||||
def self.pluralization_rules
|
||||
if defined?(@pluralization_regex) && @pluralization_regex
|
||||
return [@pluralization_regex, @pluralization_hash]
|
||||
end
|
||||
@pluralization_regex = Regexp.new("(" + @plural_rules.map {|s,p| s}.join("|") + ")$", "i")
|
||||
@pluralization_hash = Hash[*@plural_rules.flatten]
|
||||
[@pluralization_regex, @pluralization_hash]
|
||||
end
|
||||
|
||||
attr_reader :singular_of, :plural_of
|
||||
|
||||
# Convert an English word from plural to singular.
|
||||
#
|
||||
# "boys".singular #=> boy
|
||||
# "tomatoes".singular #=> tomato
|
||||
#
|
||||
# ==== Parameters
|
||||
# word<String>:: word to singularize
|
||||
#
|
||||
# ==== Returns
|
||||
# <String>:: singularized form of word
|
||||
#
|
||||
# ==== Notes
|
||||
# Aliased as singularize (a Railism)
|
||||
def self.singular(word)
|
||||
if result = singular_of[word]
|
||||
return result.dup
|
||||
end
|
||||
result = word.dup
|
||||
regex, hash = singularization_rules
|
||||
result.sub!(regex) {|m| hash[m]}
|
||||
singular_of[word] = result
|
||||
return result
|
||||
end
|
||||
|
||||
# Alias for #singular (a Railism).
|
||||
#
|
||||
alias_method(:singularize, :singular)
|
||||
|
||||
# Convert an English word from singular to plural.
|
||||
#
|
||||
# "boy".plural #=> boys
|
||||
# "tomato".plural #=> tomatoes
|
||||
#
|
||||
# ==== Parameters
|
||||
# word<String>:: word to pluralize
|
||||
#
|
||||
# ==== Returns
|
||||
# <String>:: pluralized form of word
|
||||
#
|
||||
# ==== Notes
|
||||
# Aliased as pluralize (a Railism)
|
||||
def self.plural(word)
|
||||
# special exceptions
|
||||
return "" if word == ""
|
||||
if result = plural_of[word]
|
||||
return result.dup
|
||||
end
|
||||
result = word.dup
|
||||
regex, hash = pluralization_rules
|
||||
result.sub!(regex) {|m| hash[m]}
|
||||
plural_of[word] = result
|
||||
return result
|
||||
end
|
||||
|
||||
# Alias for #plural (a Railism).
|
||||
alias_method(:pluralize, :plural)
|
||||
end
|
||||
|
||||
# One argument means singular and plural are the same.
|
||||
|
||||
word 'equipment'
|
||||
word 'fish'
|
||||
word 'grass'
|
||||
word 'hovercraft'
|
||||
word 'information'
|
||||
word 'milk'
|
||||
word 'money'
|
||||
word 'moose'
|
||||
word 'plurals'
|
||||
word 'postgres'
|
||||
word 'rain'
|
||||
word 'rice'
|
||||
word 'series'
|
||||
word 'sheep'
|
||||
word 'species'
|
||||
word 'status'
|
||||
|
||||
# Two arguments defines a singular and plural exception.
|
||||
word 'alias' , 'aliases'
|
||||
word 'analysis' , 'analyses'
|
||||
word 'axis' , 'axes'
|
||||
word 'basis' , 'bases'
|
||||
word 'buffalo' , 'buffaloes'
|
||||
word 'cactus' , 'cacti'
|
||||
word 'crisis' , 'crises'
|
||||
word 'criterion' , 'criteria'
|
||||
word 'cross' , 'crosses'
|
||||
word 'datum' , 'data'
|
||||
word 'diagnosis' , 'diagnoses'
|
||||
word 'drive' , 'drives'
|
||||
word 'erratum' , 'errata'
|
||||
word 'goose' , 'geese'
|
||||
word 'index' , 'indices'
|
||||
word 'life' , 'lives'
|
||||
word 'louse' , 'lice'
|
||||
word 'matrix' , 'matrices'
|
||||
word 'medium' , 'media'
|
||||
word 'mouse' , 'mice'
|
||||
word 'movie' , 'movies'
|
||||
word 'octopus' , 'octopi'
|
||||
word 'ox' , 'oxen'
|
||||
word 'phenomenon' , 'phenomena'
|
||||
word 'plus' , 'plusses'
|
||||
word 'potato' , 'potatoes'
|
||||
word 'quiz' , 'quizzes'
|
||||
word 'status' , 'status'
|
||||
word 'status' , 'statuses'
|
||||
word 'Swiss' , 'Swiss'
|
||||
word 'testis' , 'testes'
|
||||
word 'thesaurus' , 'thesauri'
|
||||
word 'thesis' , 'theses'
|
||||
word 'thief' , 'thieves'
|
||||
word 'tomato' , 'tomatoes'
|
||||
word 'torpedo' , 'torpedoes'
|
||||
word 'vertex' , 'vertices'
|
||||
word 'wife' , 'wives'
|
||||
|
||||
# One-way singularization exception (convert plural to singular).
|
||||
|
||||
# General rules.
|
||||
rule 'person' , 'people', true
|
||||
rule 'shoe' , 'shoes', true
|
||||
rule 'hive' , 'hives', true
|
||||
rule 'man' , 'men', true
|
||||
rule 'child' , 'children', true
|
||||
rule 'news' , 'news', true
|
||||
rule 'rf' , 'rves'
|
||||
rule 'af' , 'aves'
|
||||
rule 'ero' , 'eroes'
|
||||
rule 'man' , 'men'
|
||||
rule 'ch' , 'ches'
|
||||
rule 'sh' , 'shes'
|
||||
rule 'ss' , 'sses'
|
||||
rule 'ta' , 'tum'
|
||||
rule 'ia' , 'ium'
|
||||
rule 'ra' , 'rum'
|
||||
rule 'ay' , 'ays'
|
||||
rule 'ey' , 'eys'
|
||||
rule 'oy' , 'oys'
|
||||
rule 'uy' , 'uys'
|
||||
rule 'y' , 'ies'
|
||||
rule 'x' , 'xes'
|
||||
rule 'lf' , 'lves'
|
||||
rule 'ffe' , 'ffes'
|
||||
rule 'afe' , 'aves'
|
||||
rule 'ouse' , 'ouses'
|
||||
# more cases of words ending in -oses not being singularized properly
|
||||
# than cases of words ending in -osis
|
||||
# rule 'osis' , 'oses'
|
||||
rule 'ox' , 'oxes'
|
||||
rule 'us' , 'uses'
|
||||
rule '' , 's'
|
||||
|
||||
# One-way singular rules.
|
||||
|
||||
singular_rule 'of' , 'ofs' # proof
|
||||
singular_rule 'o' , 'oes' # hero, heroes
|
||||
singular_rule 'f' , 'ves'
|
||||
|
||||
# One-way plural rules.
|
||||
|
||||
#plural_rule 'fe' , 'ves' # safe, wife
|
||||
plural_rule 's' , 'ses'
|
||||
plural_rule 'ive' , 'ives' # don't want to snag wife
|
||||
plural_rule 'fe' , 'ves' # don't want to snag perspectives
|
||||
|
||||
end
|
Loading…
Reference in a new issue