0
+require "english/inflect"
0
# The Inflector transforms words from singular to plural, class names to table names, modularized class names to ones without,
0
# and class names to foreign keys. The default inflections for pluralization, singularization, and uncountable words are kept
0
- # A singleton instance of this class is yielded by Inflector.inflections, which can then be used to specify additional
0
- # inflection rules. Examples:
0
- # Inflector.inflections do |inflect|
0
- # inflect.plural /^(ox)$/i, '\1\2en'
0
- # inflect.singular /^(ox)en/i, '\1'
0
- # inflect.irregular 'octopus', 'octopi'
0
- # inflect.uncountable "equipment"
0
+ # This class is made available inside a block passed to Inflector.inflections, so you can add additional rules.
0
+ # Inflector.inflections
0
+ # word "octopus", "octopi"
0
+ # rule "man", "men", true
0
+ # Rules are evaluated by size, so rules you add to override specific cases should be longer than the rule
0
+ # it overrides. For instance, if you want "pta" to pluralize to "ptas", even though a general purpose rule
0
+ # for "ta" => "tum" already exists, simply add a new rule for "pta" => "ptas", and it will automatically win
0
+ # since it is longer than the old rule.
0
- # New rules are added at the top. So in the example above, the irregular rule for octopus will now be the first of the
0
- # pluralization and singularization rules that is runs. This guarantees that your rules run before any of the rules that may
0
- # already have been loaded.
0
+ # Also, single-word exceptions win over general words ("ox" pluralizes to "oxen", because it's a single word
0
+ # exception, even though "fox" pluralizes to "foxes")
0
+ # Define a general two-way exception.
0
+ # This also defines a general rule, so foo_child will correctly become
0
+ # Whole words also work if they are capitalized (Goose => Geese).
0
+ # Only use #word if you don't want the word to also work as a suffix.
0
+ # For instance, man => men also defines fireman => firemen. In that case
0
+ # use #rule, passing true as the third argument.
0
+ def word(singular, plural=nil)
0
+ plural = singular unless plural
0
+ singular_word(singular, plural)
0
+ plural_word(singular, plural)
0
+ rule(singular, plural)
0
+ def clear(type = :all)
0
+ if type == :singular || type == :all
0
+ @singularization_rules, @singularization_regex = nil, nil
0
+ if type == :plural || type == :all
+ @singular_of = {}
0
+ @singularization_rules, @singularization_regex = nil, nil
0
+ # Define a singularization exception. This is also used by #word.
0
+ def singular_word(singular, plural)
0
+ @singular_of[plural] = singular
0
+ @singular_of[plural.capitalize] = singular.capitalize
0
- attr_reader :plurals, :singulars, :uncountables
0
+ # Define a pluralization exception. This is also used by #word.
0
+ def plural_word(singular, plural)
0
+ @plural_of[singular] = plural
0
+ @plural_of[singular.capitalize] = plural.capitalize
0
- @plurals, @singulars, @uncountables = [], [], []
0
+ # Define a general rule.
0
+ # whole_word is for capitalization, since words can be
0
+ # capitalized (Man => Men)
0
+ def rule(singular, plural, whole_word = false)
0
+ singular_rule(singular, plural)
0
+ plural_rule(singular, plural)
0
+ word(singular, plural) if whole_word
0
- # Specifies a new pluralization rule and its replacement. The rule can either be a string or a regular expression.
0
- # The replacement should always be a string that may include references to the matched data from the rule.
0
- def plural(rule, replacement)
0
- @plurals.insert(0, [rule, replacement])
0
+ # Define a singularization rule.
0
+ def singular_rule(singular, plural)
0
+ @singular_rules << [singular, plural]
0
- # Specifies a new singularization rule and its replacement. The rule can either be a string or a regular expression.
0
- # The replacement should always be a string that may include references to the matched data from the rule.
0
- def singular(rule, replacement)
0
- @singulars.insert(0, [rule, replacement])
0
+ # Define a plurualization rule.
0
+ def plural_rule(singular, plural)
0
+ @plural_rules << [singular, plural]
0
- # Specifies a new irregular that applies to both pluralization and singularization at the same time. This can only be used
0
- # for strings, not regular expressions. You simply pass the irregular in singular and plural form.
0
- # irregular 'octopus', 'octopi'
0
- # irregular 'person', 'people'
0
- def irregular(singular, plural)
0
- if singular[0,1].upcase == plural[0,1].upcase
0
- plural(Regexp.new("(#{singular[0,1]})#{singular[1..-1]}$", "i"), '\1' + plural[1..-1])
0
- singular(Regexp.new("(#{plural[0,1]})#{plural[1..-1]}$", "i"), '\1' + singular[1..-1])
0
- plural(Regexp.new("#{singular[0,1].upcase}(?i)#{singular[1..-1]}$"), plural[0,1].upcase + plural[1..-1])
0
- plural(Regexp.new("#{singular[0,1].downcase}(?i)#{singular[1..-1]}$"), plural[0,1].downcase + plural[1..-1])
0
- singular(Regexp.new("#{plural[0,1].upcase}(?i)#{plural[1..-1]}$"), singular[0,1].upcase + singular[1..-1])
0
- singular(Regexp.new("#{plural[0,1].downcase}(?i)#{plural[1..-1]}$"), singular[0,1].downcase + singular[1..-1])
0
+ # Read prepared singularization rules.
0
+ def singularization_rules
0
+ if defined?(@singularization_regex) && @singularization_regex
0
+ return [@singularization_regex, @singularization_hash]
0
+ # No sorting needed: Regexen match on longest string
0
+ @singularization_regex = Regexp.new("(" + @singular_rules.map {|s,p| p}.join("|") + ")$", "i")
0
+ @singularization_hash = Hash[*@singular_rules.flatten].invert
0
+ [@singularization_regex, @singularization_hash]
0
+ # Read prepared pluralization rules.
0
+ def pluralization_rules
0
+ if defined?(@pluralization_regex) && @pluralization_regex
0
+ return [@pluralization_regex, @pluralization_hash]
0
+ @pluralization_regex = Regexp.new("(" + @plural_rules.map {|s,p| s}.join("|") + ")$", "i")
0
+ @pluralization_hash = Hash[*@plural_rules.flatten]
0
+ [@pluralization_regex, @pluralization_hash]
0
- # Add uncountable words that shouldn't be attempted inflected.
0
+ attr_reader :singular_of, :plural_of
0
+ # Convert an English word from plural to singular.
0
+ # "boys".singularize #=> boy
0
+ # "tomatoes".singularize #=> tomato
0
- # uncountable "money", "information"
0
- # uncountable %w( money information rice )
0
- def uncountable(*words)
0
- (@uncountables << words).flatten!
0
+ if result = singular_of[word]
0
+ regex, hash = singularization_rules
0
+ result.sub!(regex) {|m| hash[m]}
0
+ singular_of[word] = result
0
- # Clears the loaded inflections within a given scope (default is <tt>:all</tt>).
0
- # Give the scope as a symbol of the inflection type, the options are: <tt>:plurals</tt>,
0
- # <tt>:singulars</tt>, <tt>:uncountables</tt>.
0
+ # Convert an English word from singular to plural.
0
+ # "boy".pluralize #=> boys
0
+ # "tomato".pluralize #=> tomatoes
0
- def clear(scope = :all)
0
- @plurals, @singulars, @uncountables = [], [], []
0
- instance_variable_set "@#{scope}", []
0
+ return "" if word == ""
0
+ if result = plural_of[word]
0
+ regex, hash = pluralization_rules
0
+ result.sub!(regex) {|m| hash[m]}
0
+ plural_of[word] = result
0
- yield Inflections.instance
0
+ Inflector.instance_eval(&blk)
0
# Returns the plural form of the word in the string.
0
@@ -105,14 +167,7 @@ module Inflector
0
# "the blue mailman".pluralize #=> "the blue mailmen"
0
# "CamelOctopus".pluralize #=> "CamelOctopi"
0
- result = word.to_s.dup
0
- if word.empty? || inflections.uncountables.include?(result.downcase)
0
- inflections.plurals.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
0
+ Inflector.pluralize(word)
0
# The reverse of pluralize, returns the singular form of a word in a string.
0
@@ -125,14 +180,7 @@ module Inflector
0
# "the blue mailmen".singularize #=> "the blue mailman"
0
# "CamelOctopi".singularize #=> "CamelOctopus"
0
- result = word.to_s.dup
0
- if inflections.uncountables.include?(result.downcase)
0
- inflections.singulars.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
0
+ Inflector.singularize(word)
0
# By default, camelize converts strings to UpperCamelCase. If the argument to camelize
0
@@ -293,4 +341,4 @@ module Inflector
0
-require File.dirname(__FILE__) + '/inflections'
0
+require File.dirname(__FILE__) + '/inflections'
0
\ No newline at end of file
Comments
Do you mean @plural_of etc. here?