Merge pull request #767 from basecamp/flavorjones/active-storage-variants

Make sure the image variants we use are preprocessed
This commit is contained in:
Mike Dalessio
2025-07-18 16:25:31 -04:00
committed by GitHub
4 changed files with 46 additions and 9 deletions
+19
View File
@@ -1,6 +1,25 @@
module Attachments
extend ActiveSupport::Concern
# The variants we use must all declared here so that we can preprocess them.
#
# If they are not preprocessed, then Rails will attempt to transform the image on-the-fly when
# they are first viewed, which may be on the read replica where writing to the database is not
# allowed. Chaos will ensue if that happens.
#
# These variants are patched into ActionText::RichText in config/initializers/action_text.rb
VARIANTS = {
# vipsthumbnail used to create sized image variants has a intent setting to manage colors during
# resize. By setting an invalid intent value the gif-incompatible intent filtering is skipped and
# the gif can be rendered with all its frame intact.
#
# Only `n` is accepted as an override, using the full parameter name `intent` doesnt work.
#
# This was cargo-culted from know-it-all and I imagine it may be fixed at some point.
small: { loader: { n: -1 }, resize_to_limit: [ 800, 600 ] },
large: { loader: { n: -1 }, resize_to_limit: [ 1024, 768 ] }
}
def attachments
rich_text_record&.embeds || []
end
@@ -1,4 +1,4 @@
<% size = local_assigns[:in_gallery] ? [800, 600] : [1024, 768] %>
<% variant = Attachments::VARIANTS[local_assigns[:in_gallery] ? :small : :large] %>
<% width = blob.metadata["width"] %>
<% height = blob.metadata["height"] %>
@@ -14,10 +14,8 @@
<audio controls="true" width="100%" preload="metadata">
<source src="<%= rails_blob_url(blob) %>" type="<%= blob.content_type %>">
</audio>
<% elsif blob.variable? %>
<%= image_tag url_for(blob.variant(loader: { n: -1 }, resize_to_limit: size)), width: width, height: height %>
<% elsif blob.previewable? %>
<%= image_tag url_for(blob.preview(resize_to_limit: size)), width: width, height: height %>
<% elsif blob.variable? || blob.previewable? %>
<%= image_tag url_for(blob.variant(variant)), width: width, height: height %>
<% else %>
<span class="attachment__icon"><%= blob.filename.extension&.downcase.presence || "unknown" %></span>
<% end %>
+4 -4
View File
@@ -1,14 +1,14 @@
<% if eventable&.has_attachments? %>
<span class="event_attachments margin-block-half flex align-center gap-half">
<% eventable.attachments.each do |attachment| %>
<% size = [800, 600] %>
<% variant = Attachments::VARIANTS[:small] %>
<% width = attachment.metadata["width"] %>
<% height = attachment.metadata["height"] %>
<% if attachment.previewable? %>
<%= image_tag url_for(attachment.preview(resize_to_limit: size)), class: "attachment attachment--image", width: width, height: height %>
<%= image_tag url_for(attachment.preview(variant)), class: "attachment attachment--image", width: width, height: height %>
<% elsif attachment.variable? %>
<%= image_tag url_for(attachment.variant(resize_to_limit: size)), class: "attachment attachment--image", width: width, height: height %>
<%= image_tag url_for(attachment.variant(variant)), class: "attachment attachment--image", width: width, height: height %>
<% else %>
<div class="attachment attachment--file attachment--<%= attachment.filename.extension -%>">
<span class="attachment__icon"><%= attachment.filename.extension&.downcase.presence || "unknown" %></span>
@@ -16,4 +16,4 @@
<% end %>
<% end %>
</span>
<% end %>
<% end %>
+20
View File
@@ -0,0 +1,20 @@
module ActionText
module Extensions
module RichText
extend ActiveSupport::Concern
included do
# This overrides the default :embeds association!
has_many_attached :embeds do |attachable|
::Attachments::VARIANTS.each do |variant_name, variant_options|
attachable.variant variant_name, variant_options.merge(preprocessed: true)
end
end
end
end
end
end
ActiveSupport.on_load(:action_text_rich_text) do
include ActionText::Extensions::RichText
end