Fix broken background image after removal (#2817)
ActiveStorage::Record and ApplicationRecord used separate connection pools (from separate `connects_to` calls). This meant `belongs_to touch: true` on attachments silently failed — the card couldn't join the attachment's transaction to receive the deferred touch, so fragment caches were never invalidated after image removal. Fix by delegating `connection_pool` from ActiveStorage::Record to ApplicationRecord so they share a single pool.
This commit is contained in:
@@ -19,15 +19,15 @@ ActiveSupport.on_load(:action_text_content) do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Don't configure replica connections for ActiveStorage::Record.
|
# ApplicationRecord calls `configure_replica_connections` to set up connection pools for the
|
||||||
# When ActiveStorage uses `connects_to`, it creates a separate connection pool
|
# application models. We want ActiveStorage::Record to use the same pools for transactional
|
||||||
# from ApplicationRecord. This causes after_commit callbacks to fire in
|
# integrity, proper callback invocation, joins, etc., however ActiveStorage::Record inherits from
|
||||||
# non-deterministic order - the Attachment's create_variants callback can fire
|
# ActiveRecord::Base, not ApplicationRecord. This is how we make Active Storage always use the
|
||||||
# before the User model's upload callback, causing FileNotFoundError when
|
# ApplicationRecord connection pool.
|
||||||
# using `process: :immediately` for variants.
|
|
||||||
# See: https://github.com/rails/rails/issues/53694
|
|
||||||
ActiveSupport.on_load(:active_storage_record) do
|
ActiveSupport.on_load(:active_storage_record) do
|
||||||
configure_replica_connections
|
class << self
|
||||||
|
delegate :connection_pool, to: "ApplicationRecord"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
module ActiveStorageControllerExtensions
|
module ActiveStorageControllerExtensions
|
||||||
|
|||||||
@@ -57,6 +57,32 @@ class Storage::NoReuseTest < ActiveSupport::TestCase
|
|||||||
).count
|
).count
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "purge touches the record to invalidate cache" do
|
||||||
|
card = @board.cards.create!(title: "Card", creator: users(:david))
|
||||||
|
card.image.attach(io: file_fixture("moon.jpg").open, filename: "moon.jpg", content_type: "image/jpeg")
|
||||||
|
|
||||||
|
original_updated_at = card.reload.updated_at
|
||||||
|
|
||||||
|
travel 1.second do
|
||||||
|
card.image.purge
|
||||||
|
end
|
||||||
|
|
||||||
|
assert card.reload.updated_at > original_updated_at
|
||||||
|
end
|
||||||
|
|
||||||
|
test "purge_later touches the record to invalidate cache" do
|
||||||
|
card = @board.cards.create!(title: "Card", creator: users(:david))
|
||||||
|
card.image.attach(io: file_fixture("moon.jpg").open, filename: "moon.jpg", content_type: "image/jpeg")
|
||||||
|
|
||||||
|
original_updated_at = card.reload.updated_at
|
||||||
|
|
||||||
|
travel 1.second do
|
||||||
|
card.image.purge_later
|
||||||
|
end
|
||||||
|
|
||||||
|
assert card.reload.updated_at > original_updated_at
|
||||||
|
end
|
||||||
|
|
||||||
test "purge_later does not purge blob when still attached elsewhere" do
|
test "purge_later does not purge blob when still attached elsewhere" do
|
||||||
file = file_fixture("moon.jpg")
|
file = file_fixture("moon.jpg")
|
||||||
blob = ActiveStorage::Blob.create_and_upload! \
|
blob = ActiveStorage::Blob.create_and_upload! \
|
||||||
|
|||||||
Reference in New Issue
Block a user