Module: Philiprehberger::Pluralize

Defined in:
lib/philiprehberger/pluralize.rb,
lib/philiprehberger/pluralize/rules.rb,
lib/philiprehberger/pluralize/version.rb,
lib/philiprehberger/pluralize/inflections.rb

Defined Under Namespace

Modules: Inflections, Rules Classes: Error

Constant Summary collapse

VERSION =
'0.3.0'

Class Method Summary collapse

Class Method Details

.camel_case(str) ⇒ String

Convert a string to PascalCase

Parameters:

  • str (String)

    the string to convert

Returns:

  • (String)

    PascalCase string



191
192
193
# File 'lib/philiprehberger/pluralize.rb', line 191

def camel_case(str)
  Inflections.camel_case(str)
end

.capitalize_and_pluralize(word) ⇒ String

Capitalize a word and return its plural form

Useful for sentence-style output such as “People” or “Children”. Preserves irregular and uncountable handling.

Parameters:

  • word (String)

    the word to capitalize and pluralize

Returns:

  • (String)

    the capitalized plural form



142
143
144
145
146
# File 'lib/philiprehberger/pluralize.rb', line 142

def capitalize_and_pluralize(word)
  return word if word.nil? || word.strip.empty?

  plural(word.downcase).capitalize
end

.count(n, word, style: :numeric) ⇒ String

Format a count with the appropriate singular or plural word

Parameters:

  • n (Integer)

    the count

  • word (String)

    the word to inflect

  • style (Symbol) (defaults to: :numeric)

    :numeric (default) or :words (spell out numbers <= 12)

Returns:

  • (String)

    the formatted count string



97
98
99
100
101
# File 'lib/philiprehberger/pluralize.rb', line 97

def count(n, word, style: :numeric)
  inflected = n == 1 ? singular(word) : plural(word)
  prefix = style == :words && n >= 0 && n <= 12 ? number_to_word(n) : n.to_s
  "#{prefix} #{inflected}"
end

.humanize(str) ⇒ String

Convert an underscored string to a human-readable form

Parameters:

  • str (String)

    the string to convert

Returns:

  • (String)

    humanized string



215
216
217
# File 'lib/philiprehberger/pluralize.rb', line 215

def humanize(str)
  Inflections.humanize(str)
end

.irregular(singular_word, plural_word) ⇒ void

This method returns an undefined value.

Register an irregular singular/plural pair

Parameters:

  • singular_word (String)

    the singular form

  • plural_word (String)

    the plural form

Raises:

  • (ArgumentError)


153
154
155
156
157
# File 'lib/philiprehberger/pluralize.rb', line 153

def irregular(singular_word, plural_word)
  raise ArgumentError, 'singular and plural must not be nil or empty' if blank?(singular_word) || blank?(plural_word)

  @custom_irregulars[singular_word.downcase] = plural_word.downcase
end

.irregularsHash{String => String}

List custom-registered irregular singular/plural pairs

Returns a frozen copy so callers cannot mutate internal state.

Returns:

  • (Hash{String => String})

    singular => plural mapping



174
175
176
# File 'lib/philiprehberger/pluralize.rb', line 174

def irregulars
  @custom_irregulars.dup.freeze
end

.ordinal(n) ⇒ String

Convert a number to its ordinal word representation (up to 100)

Parameters:

  • n (Integer)

    the number (1-100)

Returns:

  • (String)

    the ordinal word

Raises:

  • (ArgumentError)


85
86
87
88
89
# File 'lib/philiprehberger/pluralize.rb', line 85

def ordinal(n)
  raise ArgumentError, 'ordinal supports numbers from 1 to 100' if n < 1 || n > 100

  ORDINALS[n] || compound_ordinal(n)
end

.plural(word) ⇒ String

Return the plural form of a word

Handles hyphenated compound words:

  • X-in-Y / X-of-Y patterns pluralize the first word

  • Other compounds pluralize the last word

Parameters:

  • word (String)

    the word to pluralize

Returns:

  • (String)

    the plural form



24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/philiprehberger/pluralize.rb', line 24

def plural(word)
  return word if word.nil? || word.strip.empty?

  return pluralize_hyphenated(word) if word.include?('-')

  lowered = word.downcase
  return word if uncountable?(lowered)

  irregular = find_irregular(lowered)
  return preserve_case(word, irregular) if irregular

  apply_rules(word, Rules::PLURALS)
end

.plural?(word) ⇒ Boolean

Return true if the word appears to be plural

Uses a simple heuristic: singularize the word, and if the result differs from the input, it is likely plural.

Parameters:

  • word (String)

    the word to check

Returns:

  • (Boolean)


75
76
77
78
79
# File 'lib/philiprehberger/pluralize.rb', line 75

def plural?(word)
  return false if word.nil? || word.strip.empty?

  singular(word) != word
end

.pluralize(n, singular_word, plural_word = nil) ⇒ String

Format a count with the correct singular or plural form

Rails-style helper: pass a count, a singular form, and optionally an explicit plural form. When plural is omitted, the plural is derived from the singular via .plural.

Parameters:

  • n (Integer)

    the count

  • singular_word (String)

    the singular form

  • plural_word (String, nil) (defaults to: nil)

    optional explicit plural form

Returns:

  • (String)

    the formatted count string, e.g. “5 octopi”

Raises:

  • (ArgumentError)


127
128
129
130
131
132
133
# File 'lib/philiprehberger/pluralize.rb', line 127

def pluralize(n, singular_word, plural_word = nil)
  raise ArgumentError, 'count must be an Integer' unless n.is_a?(Integer)
  raise ArgumentError, 'singular word must not be nil or empty' if singular_word.nil? || singular_word.strip.empty?

  word = n == 1 ? singular_word : (plural_word || plural(singular_word))
  "#{n} #{word}"
end

.possessive(word) ⇒ String

Generate the possessive form of a word

Parameters:

  • word (String)

    the word

Returns:

  • (String)

    the possessive form



58
59
60
61
62
63
64
65
66
# File 'lib/philiprehberger/pluralize.rb', line 58

def possessive(word)
  return word if word.nil? || word.strip.empty?

  if word.end_with?('s')
    "#{word}'"
  else
    "#{word}'s"
  end
end

.reset!void

This method returns an undefined value.

Reset custom irregular and uncountable rules



222
223
224
225
# File 'lib/philiprehberger/pluralize.rb', line 222

def reset!
  @custom_irregulars = {}
  @custom_uncountables = Set.new
end

.singular(word) ⇒ String

Return the singular form of a word

Parameters:

  • word (String)

    the word to singularize

Returns:

  • (String)

    the singular form



42
43
44
45
46
47
48
49
50
51
52
# File 'lib/philiprehberger/pluralize.rb', line 42

def singular(word)
  return word if word.nil? || word.strip.empty?

  lowered = word.downcase
  return word if uncountable?(lowered)

  irregular = find_irregular_inverse(lowered)
  return preserve_case(word, irregular) if irregular

  apply_rules(word, Rules::SINGULARS)
end

.snake_case(str) ⇒ String

Convert a string to snake_case

Parameters:

  • str (String)

    the string to convert

Returns:

  • (String)

    snake_case string



199
200
201
# File 'lib/philiprehberger/pluralize.rb', line 199

def snake_case(str)
  Inflections.snake_case(str)
end

.titleize(str) ⇒ String

Convert a string to Title Case

Parameters:

  • str (String)

    the string to convert

Returns:

  • (String)

    titleized string



207
208
209
# File 'lib/philiprehberger/pluralize.rb', line 207

def titleize(str)
  Inflections.titleize(str)
end

.uncountable(word) ⇒ void

This method returns an undefined value.

Register a word as uncountable

Parameters:

  • word (String)

    the uncountable word

Raises:

  • (ArgumentError)


163
164
165
166
167
# File 'lib/philiprehberger/pluralize.rb', line 163

def uncountable(word)
  raise ArgumentError, 'uncountable word must not be nil or empty' if blank?(word)

  @custom_uncountables.add(word.downcase)
end

.uncountable?(word) ⇒ Boolean

Return true if the word is uncountable (same singular and plural form)

Checks both the built-in uncountable list and any custom uncountables registered via .uncountable.

Parameters:

  • word (String)

    the word to check

Returns:

  • (Boolean)


110
111
112
113
114
115
# File 'lib/philiprehberger/pluralize.rb', line 110

def uncountable?(word)
  return false if word.nil? || word.strip.empty?

  lowered = word.downcase
  Rules::UNCOUNTABLES.include?(lowered) || @custom_uncountables.include?(lowered)
end

.uncountablesArray<String>

List custom-registered uncountable words

Returns a frozen copy so callers cannot mutate internal state.

Returns:

  • (Array<String>)

    sorted list of uncountable words



183
184
185
# File 'lib/philiprehberger/pluralize.rb', line 183

def uncountables
  @custom_uncountables.to_a.sort.freeze
end