Module: Railbow::NameFormatter

Defined in:
lib/railbow/name_formatter.rb

Overview

Formats person names using a pattern language inspired by date-format strings.

Tokens (repeat the letter to control length; 4+ means full word):

F / FF / FFF / FFFF+  — first name (1 char, 2 chars, … , full)
L / LL / LLL / LLLL+  — last name
M / MM / MMM / MMMM+  — middle name(s)

Any other characters (spaces, dots, commas) are literals and pass through.

Named presets:

"initials"        → "F L"
"short"           → "FF L"
"first_name"      → "FFFF"
"last_name"       → "LLLL"
"full_name"       → "FFFF MMMM LLLL"
"full_name_short" → "FFFF L."

Constant Summary collapse

PRESETS =
{
  "initials" => "F L",
  "short" => "FF L",
  "first_name" => "FFFF",
  "last_name" => "LLLL",
  "full_name" => "FFFF MMMM LLLL",
  "full_name_short" => "FFFF L."
}.freeze
TOKEN_RE =
/([FLM])\1*/
EMPTY =

Sentinel inserted when a token expands to empty, so surrounding literals that only make sense next to a value can be cleaned up.

"\x00"

Class Method Summary collapse

Class Method Details

.format(name, pattern) ⇒ Object

Format a name according to a pattern or preset name. Returns "" for nil/empty input.



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/railbow/name_formatter.rb', line 39

def format(name, pattern)
  return "" if name.nil? || name.empty?

  pattern = PRESETS.fetch(pattern, pattern)
  parts = name.split(/[\s._-]+/)

  first = parts.first || ""
  last = (parts.size > 1) ? parts.last : ""
  middle = (parts.size > 2) ? parts[1..-2] : []

  result = pattern.gsub(TOKEN_RE) do |match|
    letter = match[0]
    len = match.length

    expanded = case letter
    when "F" then truncate(first, len)
    when "L" then truncate(last, len)
    when "M" then middle.map { |m| truncate(m, len) }.join(" ")
    end

    expanded.empty? ? EMPTY : expanded
  end

  # Remove sentinels and any adjacent non-letter literals (dots, commas, spaces)
  result.gsub(/[^a-zA-Z\x00]*\x00[^a-zA-Z\x00]*/, " ")
    .gsub(/  +/, " ")
    .strip
end