Skip to content

Instantly share code, notes, and snippets.

@brenogazzola
Last active October 17, 2022 15:34
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save brenogazzola/9f6c0c307f1a00c260a0818557dc3587 to your computer and use it in GitHub Desktop.
Save brenogazzola/9f6c0c307f1a00c260a0818557dc3587 to your computer and use it in GitHub Desktop.
Creating a custom ActiveStorage controller to generate "pretty urls" or help migration from another lib
# This demonstrates how we create a SEO friendly url for the previews of the artworks we sell.
#
# This is the URL we want:
# https://festalab.com.br/image/invitation/birthday/carnival.jpg
#
# First, the route.
#
# "model" is the name of the active storage model that has the preview.
# "classification" and "identifier" are together a unique key for the records.
Rails.application.routes.draw do
get "image/:model/:classification/:identifier", to: "imager/previews#show", as: :imager_preview
# model : invitation
# classification: birthday
# identifier : carnival
end
# Here's the custom controller. This is based on Rails 7.0, so you might have to change
# which controller you inherit from in previous Rails versions.
#
class Imager::PreviewsController < ActiveStorage::BaseController
include Imager::SetBlob
include Imager::SetVariationKey
def show
http_cache_forever public: true do
send_blob_stream representation.image
end
rescue => error
logger.error(error) if Rails.env.production?
head :unprocessable_entity
end
private
def representation
@representation ||= @blob.representation(@variation_key).processed
end
end
# This is the SetBlob concern. Instead of using the default signed_id param that active storage uses, we use our
# own parameters to locate the blob.
module Imager::SetBlob #:nodoc:
extend ActiveSupport::Concern
included do
before_action :set_blob
end
private
def set_blob
model = params[:model].constantize
classification = params[:classification]
identifier = params[:identifier]
@blob = model.find_by(classification: classification, identifier: identifier).preview.blob
rescue => error
logger.error(error) if Rails.env.production?
head :not_found
end
end
# This is the SetVariation concern. Instead of using the default variation_key param, we define our own transformations
# frozen_string_literal: true
module Imager::SetVariationKey #:nodoc:
extend ActiveSupport::Concern
included do
before_action :set_variation_key
end
private
def set_variation_key
@variation_key = ActiveStorage::Variation.new(transformations)
rescue => error
logger.error(error) if Rails.env.production?
head :not_acceptable
end
def transformations
{ format: :jpg, saver: {strip: true, quality: 80 }}
end
end
@danielbwa
Copy link

danielbwa commented Oct 17, 2022

Thanks!

I've chosen to include ActiveStorage::Streaming instead of extending ActiveStorage::BaseController

class PreviewController
  include ActiveStorage::Streaming
  
  def show
    http_cache_forever(public: true) do
      send_blob_stream @model
    end
  end
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment