1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# Each card's search key (Admin::Search::Key) as JSON, so a search
# reads these rather than building every contact
# (docs/plans/2026-10-17-search-keys.md). Index, like card_properties:
# filled here through the app's own Search.key, since what it must
# agree with is the search that reads it.
require "pro_tacts/admin/search"
require "pro_tacts/contact"
require "pro_tacts/vcard"
Sequel.migration do
up do
create_table(:search_keys, strict: true) do
foreign_key :card_id, :cards, type: String, text: true, primary_key: true, null: false, on_delete: :cascade
String :key, text: true, null: false
end
self[:cards].order(:id).each do |row|
id = row.fetch(:id)
contact = ProTacts::Contact.new(id:, stored: ProTacts::VCard.new(row.fetch(:vcard)), birthday: nil, inherited: [])
self[:search_keys].insert(card_id: id, key: ProTacts::Admin::Search.key(contact).to_json)
end
end
down do
drop_table(:search_keys)
end
end