diff --git a/app/models/portal.rb b/app/models/portal.rb index 9d2da6965..dfd5347aa 100644 --- a/app/models/portal.rb +++ b/app/models/portal.rb @@ -50,6 +50,13 @@ class Portal < ApplicationRecord schema: PortalConfigSchema::CONFIG_PARAMS_SCHEMA, attribute_resolver: ->(record) { record.config } + # Portal name/slug are embedded as help_center into the cached inbox payload + # (api/v1/models/_inbox.json.jbuilder), so portal changes must bump the + # account's inbox cache key. Destroy is covered too: dependent: :nullify + # detaches inboxes via update_all and skips their callbacks. + after_update_commit -> { account.update_cache_key('inbox') } + after_destroy_commit -> { account.update_cache_key('inbox') } + scope :active, -> { where(archived: false) } # TODO: 'website_token' is an unused reserved key; remove with a migration that scrubs it from existing portals' config diff --git a/spec/models/portal_spec.rb b/spec/models/portal_spec.rb index c71a458fd..ce58da652 100644 --- a/spec/models/portal_spec.rb +++ b/spec/models/portal_spec.rb @@ -150,4 +150,22 @@ RSpec.describe Portal do expect(portal.display_title).to eq('Help Center | Acme') end end + + describe 'inbox cache invalidation' do + # Portal name/slug are embedded as help_center into the cached inbox + # payload (api/v1/models/_inbox.json.jbuilder), so portal changes must bump + # the account's inbox cache key. + let(:account) { create(:account) } + let!(:portal) { create(:portal, account: account) } + + it 'bumps the inbox cache key after update' do + expect(account).to receive(:update_cache_key).with('inbox') + portal.update!(name: 'Renamed Portal') + end + + it 'bumps the inbox cache key after destroy' do + expect(account).to receive(:update_cache_key).with('inbox') + portal.destroy! + end + end end