Take this with a grain of salt, since I’m just a regular contributor and not a member of the Rails team, but two things you should keep in mind
1 - Most Rails features are extractions of a production app, and therefore tailored to a very specific use case. The community later expands that use case. For example, Active Storage originated from Basecamp where it was only responsible for serving private files, so it had no support for CDN caching
2 - When evaluating PRs, my experience is that Rails maintainers put a lot of emphasis on “what is Rails responsability and what is not”. This is where your use case is on. Active Storage responsibility is “uploading files to storage, serving them, and extracting useful information from them, such as image dimensions.” This means that AST is not expected to have any knowledge of where the file originate from or how it will be used. And giving a file a title falls under “AST knows how a file will be used”.
You did not mention your use case, so I will try to explain with an example. Let’s say your product team tells you this: “Users can create galleries, and each gallery has many photos”. Simple enough, and you could implement something like this:
class Gallery < ApplicationRecord
belongs_to :user
has_many_attached :photos
end
@gallery.photos.each do |photo|
image_tag photo
end
Of course, things are never that simple. After you show your PR, the product team will say "That’s mighty fine. But we also need to let them choose change the position of the photos, give each one a title and description, and oh, when they upload it they must be able to resize and crop it. Also, we want it optimized so it displays fast on mobile phones”
This is where you might think: “Well, I need to add those things to the attachments or blobs”. Unfortunately you’d fall under “this is not Active Storage responsability. AST is not supposed to know how an image will be used”. The expected implementation is this:
class Gallery < ApplicationRecord
belongs_to :user
has_many :photos
end
class Photo < ApplicationRecord
belongs_to :gallery
has_one_attached :file
validates :title, presence: true
validates :description presence: true
validates :position, presence: true
validates :crop_x, presence: true
validates :crop_y, presence: true
validates :width, presence: true
validates :height, presence: true
def thumbnail
file.variant {
saver: { strip: true, quality: 80, interlace: true }, format: "jpg" },
crop: [crop_x, crop_y, width, height],
resize_to_limit: [818, nil]
}
end
end
@gallery.photos.order(:position).each do |photo|
image_tag photo.thumbnail
end