groups: check submitted members against ids alone
Both group saves read every card in the book, photos and all, to learn
which ids exist. Store#contact_ids reads the ids.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GNVLyiMrZJ7sZctEYq6WCM
diff --git a/lib/pro_tacts/store.rb b/lib/pro_tacts/store.rb
index 2bba8f3..1487fa2 100644
--- a/lib/pro_tacts/store.rb
+++ b/lib/pro_tacts/store.rb
@@ -246,6 +246,13 @@ module ProTacts
}
end
+ # Every contact's id, in #contacts' order, for a caller that only
+ # asks which cards exist: no card is read to answer.
+ #: () -> Array[String]
+ def contact_ids
+ cards.order(:id).select_map(:id).map(&:to_s)
+ end
+
# Every contact paired with its card's updated_at, newest first — the
# read behind any "recently updated" surface. Same shape and cost as
# #contacts, ordered by the column SQLite already stamps rather than
diff --git a/lib/pro_tacts/web/groups.rb b/lib/pro_tacts/web/groups.rb
index 369b4c8..e013526 100644
--- a/lib/pro_tacts/web/groups.rb
+++ b/lib/pro_tacts/web/groups.rb
@@ -121,7 +121,7 @@ module ProTacts
submitted = r.params["members"]
members =
if submitted.is_a?(Array)
- submitted.map(&:to_s) & store.contacts.map(&:id)
+ submitted.map(&:to_s) & store.contact_ids
else
group.members
end #: Array[String]
@@ -156,7 +156,7 @@ module ProTacts
group = store.group(id)
return if group.nil?
- known = store.contacts.map(&:id)
+ known = store.contact_ids
checked = ids_in(r.params["members"]) & known
was = ids_in(r.params["was"]) & known
store.edit_members(id, join: checked - was, leave: was - checked)