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?