Format.initials: one letter, not a guess at two
Review feedback: splitting a bare FN on whitespace and taking the
first letter of up to two words was still a guess dressed up as two
initials. Falling back from a missing N property to a single first
letter is honest about having only unstructured text to go on.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SYiigu3aFNaiTP9SyKW9mX
change
commit e6a70832f2efc8c2416048ea32592bdc9aa49e4c
author Claude <noreply@anthropic.com>
date
parent f4b3253a
diff --git a/lib/pro_tacts/admin/contact_fields.rb b/lib/pro_tacts/admin/contact_fields.rb
index 5a261d9..cbdba5b 100644
--- a/lib/pro_tacts/admin/contact_fields.rb
+++ b/lib/pro_tacts/admin/contact_fields.rb
@@ -51,10 +51,10 @@ module ProTacts
       # RFC 2426 section 3.1.2: N is Family;Given;Additional;Prefixes;
       # Suffixes. A given and family name are structured data — reading
       # them is the real answer to "what are this contact's initials,"
-      # not guessing at word boundaries in the free-text FN the way
-      # Format.initials does. That guess is kept only as the fallback
-      # for a card with no N at all (an organization's own address-book
-      # entry, say, which has a name but no person to split in two).
+      # rather than guessing at where a first/last split falls in the
+      # free-text FN. A card with no N at all (an organization's own
+      # address-book entry, say, with a name but no person to split in
+      # two) falls back to Format.initials' single first letter.
       #: (VCard::Property? property) -> String?
       def initials_from(property)
         return nil if property.nil?
diff --git a/lib/pro_tacts/admin/format.rb b/lib/pro_tacts/admin/format.rb
index 6016a48..e558fb8 100644
--- a/lib/pro_tacts/admin/format.rb
+++ b/lib/pro_tacts/admin/format.rb
@@ -4,9 +4,13 @@ module ProTacts
   module Admin
     # Small display helpers shared by the admin views.
     module Format
+      # The first letter of a name with nothing more structured to go
+      # on — an id, or a display name with no N property behind it
+      # (see ContactFields#initials_from). One letter rather than a
+      # guess at where a first/last split would fall in free text.
       #: (String name) -> String
       def self.initials(name)
-        name.to_s.split(/\s+/).reject(&:empty?).first(2).map { it[0].upcase }.join
+        name.to_s.strip[0].to_s.upcase
       end
 
       # A card's updated_at, UTC ISO 8601 to the millisecond (see
diff --git a/test/pro_tacts/admin/test_contact_fields.rb b/test/pro_tacts/admin/test_contact_fields.rb
index 0e68165..afd416a 100644
--- a/test/pro_tacts/admin/test_contact_fields.rb
+++ b/test/pro_tacts/admin/test_contact_fields.rb
@@ -25,11 +25,11 @@ class ContactFieldsTest < Minitest::Test
   end
 
   # A card with no N at all — an organization's own entry, say — falls
-  # back to Format.initials' word-splitting guess on FN.
+  # back to Format.initials' single first letter of FN.
   def test_initials_fall_back_to_the_display_name_with_no_n_property
     no_n = "BEGIN:VCARD\r\nVERSION:3.0\r\nFN:Riverside Elementary\r\nUID:office\r\nEND:VCARD\r\n"
 
-    assert_equal "RE", fields(no_n).initials
+    assert_equal "R", fields(no_n).initials
   end
 
   # N with only one of given/family present (a mononym, or a card that
diff --git a/test/pro_tacts/admin/test_format.rb b/test/pro_tacts/admin/test_format.rb
index 315ebf3..c8710b3 100644
--- a/test/pro_tacts/admin/test_format.rb
+++ b/test/pro_tacts/admin/test_format.rb
@@ -3,10 +3,10 @@ require_relative "../../test_helper"
 require "pro_tacts/admin/format"
 
 class FormatTest < Minitest::Test
-  def test_initials_takes_the_first_letter_of_up_to_two_words
-    assert_equal "AL", ProTacts::Admin::Format.initials("Ada Lovelace")
+  def test_initials_is_the_first_letter_of_the_name
+    assert_equal "A", ProTacts::Admin::Format.initials("Ada Lovelace")
     assert_equal "A", ProTacts::Admin::Format.initials("Ada")
-    assert_equal "RE", ProTacts::Admin::Format.initials("Riverside Elementary Front Office")
+    assert_equal "R", ProTacts::Admin::Format.initials("Riverside Elementary Front Office")
   end
 
   def test_initials_of_a_blank_name_is_blank