Give Contact and Group a console-readable inspect
Assisted-by: GLM-5.3 via pi
change vzmpxkwpnkslkuymvrzspmqwywsqonmq
commit b65cb1fb01ae7369b4a68ba831b2ff337c6f4a6c
author Alpha Chen <alpha@kejadlen.dev>
date
parent mvrrolop
diff --git a/lib/pro_tacts/contact.rb b/lib/pro_tacts/contact.rb
index af9d2b9..f66b610 100644
--- a/lib/pro_tacts/contact.rb
+++ b/lib/pro_tacts/contact.rb
@@ -188,6 +188,18 @@ module ProTacts
       @etag = self.class.etag_for(vcard)
     end
 
+    # What a console session sees for one (console.rb): the default
+    # would carry the stored card's whole bytes through @stored, which
+    # makes a listing of contacts unreadable at a prompt. #name
+    # composes and parses the card; no app path inspects a contact,
+    # so the parse is a session's price alone.
+    #: () -> String
+    def inspect
+      parts = ["id=#{id.inspect}"]
+      parts << "name=#{name.inspect}" if name
+      "#<#{self.class.name} #{parts.join(" ")}>"
+    end
+
     # The image formats a decoded PHOTO is recognized by, prefix to
     # mime type. A picture's type is read off the decoded bytes rather
     # than the TYPE parameter because magic bytes cannot mislabel what
diff --git a/lib/pro_tacts/store.rb b/lib/pro_tacts/store.rb
index 751e59c..b38989f 100644
--- a/lib/pro_tacts/store.rb
+++ b/lib/pro_tacts/store.rb
@@ -121,6 +121,14 @@ module ProTacts
       def version
         Digest::SHA256.hexdigest([name, lines, members].to_json)
       end
+
+      # What a console session sees for one (console.rb): the Data
+      # class's own inspect would carry every lent line and every
+      # member id, and a listing of groups is unreadable at a prompt.
+      #: () -> String
+      def inspect
+        "#<#{self.class.name} id=#{id.inspect} label=#{label.inspect} members=#{members.length}>"
+      end
     end
 
     # SQLite has no ON UPDATE, so the column default stamps a row on
diff --git a/test/pro_tacts/test_contact.rb b/test/pro_tacts/test_contact.rb
index e44fd49..91ac99d 100644
--- a/test/pro_tacts/test_contact.rb
+++ b/test/pro_tacts/test_contact.rb
@@ -95,6 +95,16 @@ class ContactTest < Minitest::Test
     assert_equal "Ada Lovelace", contact(STRUCTURED).name
   end
 
+  def test_inspect_shows_the_id_and_name_and_not_the_card
+    assert_equal %(#<ProTacts::Contact id="aiden" name="Aiden">), contact.inspect
+  end
+
+  def test_inspect_without_a_name_shows_only_the_id
+    bare = "BEGIN:VCARD\r\nVERSION:3.0\r\nUID:none\r\nEND:VCARD\r\n"
+
+    assert_equal %(#<ProTacts::Contact id="aiden">), contact(bare).inspect
+  end
+
   def test_reads_the_name_components
     assert_equal ["Lovelace", "Ada", nil, nil, nil], contact(STRUCTURED).name_components
   end
diff --git a/test/pro_tacts/test_store.rb b/test/pro_tacts/test_store.rb
index 23e1013..bb50c1c 100644
--- a/test/pro_tacts/test_store.rb
+++ b/test/pro_tacts/test_store.rb
@@ -1179,6 +1179,16 @@ class StoreTest < Minitest::Test
   # spelled the name. Everything else is refused — a phone or an email
   # reaches a person rather than a household, and a grouped ADR is half
   # of a labeled property whose other half no group may hold.
+  def test_a_group_inspects_to_its_label_and_member_count
+    with_store({"aiden" => AIDEN, "znorth" => ZED}) do |store|
+      id = FixtureData.seed_group(store, name: "Household", members: %w[znorth aiden])
+      nameless = store.create_group
+
+      assert_equal %(#<ProTacts::Store::Group id="#{id}" label="Household" members=2>), store.group(id).inspect
+      assert_equal %(#<ProTacts::Store::Group id="#{nameless}" label="#{nameless}" members=0>), store.group(nameless).inspect
+    end
+  end
+
   def test_a_group_holds_only_addresses_and_notes
     with_store({"aiden" => AIDEN}) do |store|
       properties = database(store)[:group_properties]