Issue using custom file / blob keys in Rails / ActiveStorage

Viewed 29

I'm getting a strange problem where the linked files cannot be found / linked properly when using custom keys in both development & production. Whilst I got the solution to this, I'm curious to hear if anyone else has come across this issue and knows what causes this in the background.

Setup: I'm on Ubuntu 20.04 using a pretty vanilla Rails 7 CRUD app. In production, we're using AWS S3. The model we're going to work with is shown below

***holiday.rb***
class Holiday < ApplicationRecord
  [...]
  has_one_attached :cover_pic
  [...]
end

Default behavior: upon saving, Rails will generate a random string as the blob key (LHASLJKAWE243234AKSJD), which is also the "filename" saved on S3. When I back up my S3 bucket, I will end up with a lot of inpenetrable filenames. My controller looks like this (simplified):

***holidays_controller.rb***
class HolidaysController < ApplicationController
  [...]
  def create
    @holiday = Holiday.new(holiday_params)
    if @holiday.save
      redirect_to edit_holiday_url(@holiday)
    else
      render :new
    end
  end
  [...]
end

The S3 file backup is borderline useless / impossible to understand without the db (where ActiveStorage) stores all the associations between the holiday entries & actual pictures using the blob table.

Therefore, I had the glorious idea to use custom keys for the blobs so that when I backup my S3 to my local machine, it's neatly arranged in "folders" (separated by the "/") in roughly speaking the following format:

"user1@gmail.com/holiday_pictures/[upload_date]_cover-pic-[randomizedstring].#{File.extname(cover_pic)}"

I've made it to work by placing this renaming logic before the initial save, so the below works:

***holidays_controller.rb WORKS***
class HolidaysController < ApplicationController
  [...]
  def create
    @holiday = Holiday.new(holiday_params)
    @cover_pic = holiday_params[:cover_pic]
    @holiday.cover_pic.attach(
      io: StringIO.new(@cover_pic),
      filename: "#{current_user.email} #{Time.now} #{@holiday.name}.#{File.extname(@cover_pic)}",
      key: "#{current_user.email}/holiday_pictures/#{Time.now}_cover-pic-#{SecureRandom.hex(6)}.#{File.extname(@cover_pic)}",
    )
    if @holiday.save
      redirect_to edit_holiday_url(@holiday)
    else
      render :new
    end
  end
  [...]
end

However, the below does not work - the picture is just kind of broken, and frankly I'm a bit baffled as to why.

***holidays_controller.rb NOT WORKING***
class HolidaysController < ApplicationController
  [...]
  def create
    @holiday = Holiday.new(holiday_params)
    @cover_pic = holiday_params[:cover_pic]
    if @holiday.save
      @holiday.cover_pic.attach(
        io: StringIO.new(@cover_pic),
        filename: "#{current_user.email} #{Time.now} #{@holiday.name}.#{File.extname(@cover_pic)}",
        key: "#{current_user.email}/holiday_pictures/#{Time.now}_cover-pic-#{SecureRandom.hex(6)}.#{File.extname(@cover_pic)}",
      )
      redirect_to edit_holiday_url(@holiday)
    else
      render :new
    end
  end
  [...]
end

Does anyone have a hint as to what's going on in the background?

0 Answers
Related