Module: Bible270::Names
- Defined in:
- lib/bible270/names.rb
Overview
Readers are known to each other by name beside their reflections, so a first and last name are both required wherever a name is set: at email sign-in, when a reader edits their own, and when an admin edits someone else's.
Kept free of Rails so the rules can be tested on their own.
Class Method Summary collapse
-
.first_with_last_initial(first, last) ⇒ Object
"Andrew vonderLuft" -> "Andrew v." Particles are kept out of the initial: "von der Luft" gives "L.", not "v.", since the last word is the one people are known by.
-
.normalize(first, last) ⇒ Object
A first and last name, or nil when either is missing.
-
.split_display_name(display_name) ⇒ Object
Best effort at splitting a single name, for readers who arrived through OmniAuth with only a display name.
-
.squish(value) ⇒ Object
Collapse runs of whitespace, including the non-breaking space that arrives from copy-paste, and trim.
- .valid?(first, last) ⇒ Boolean
Class Method Details
.first_with_last_initial(first, last) ⇒ Object
"Andrew vonderLuft" -> "Andrew v." Particles are kept out of the initial: "von der Luft" gives "L.", not "v.", since the last word is the one people are known by.
39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/bible270/names.rb', line 39 def first_with_last_initial(first, last) first_name = squish(first) surname = squish(last) return first_name if surname.empty? initial = surname.split.last[0] return first_name if initial.nil? # Not upcased: a lowercase surname is usually deliberate (vonderLuft), and # forcing "V." would override how someone writes their own name. "#{first_name} #{initial}.".strip end |
.normalize(first, last) ⇒ Object
A first and last name, or nil when either is missing. Returns the pieces plus the display name built from them, so every caller derives it the same way rather than assembling it locally.
21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/bible270/names.rb', line 21 def normalize(first, last) first_name = squish(first) last_name = squish(last) return nil if first_name.empty? || last_name.empty? # Only persisted columns belong here — this hash is assigned straight onto # the model. Anything derived (see first_with_last_initial) is computed on # demand, so it can't go stale when a name is edited. { first_name: first_name, last_name: last_name, display_name: "#{first_name} #{last_name}" } end |
.split_display_name(display_name) ⇒ Object
Best effort at splitting a single name, for readers who arrived through OmniAuth with only a display name. Everything after the first word is the surname, so "Andrew von der Luft" keeps its particles together.
Deliberately not called split: a module method with the same name as
String#split invites a bare split(...) inside this module to resolve here
instead, and RuboCop's Style/StringChars autocorrect has been known to
rewrite split calls into a receiverless chars, which then resolves
against the module and fails confusingly.
65 66 67 68 69 70 |
# File 'lib/bible270/names.rb', line 65 def split_display_name(display_name) parts = squish(display_name).split return nil if parts.size < 2 { first_name: parts.first, last_name: parts[1..].join(' ') } end |
.squish(value) ⇒ Object
Collapse runs of whitespace, including the non-breaking space that arrives from copy-paste, and trim.
14 15 16 |
# File 'lib/bible270/names.rb', line 14 def squish(value) value.to_s.tr("\u00A0", ' ').gsub(%r{\s+}, ' ').strip end |
.valid?(first, last) ⇒ Boolean
52 53 54 |
# File 'lib/bible270/names.rb', line 52 def valid?(first, last) !normalize(first, last).nil? end |