Can you _remove_ a variant from ActiveStorage? - ruby-on-rails

Using ActiveStorage in Rails, variants are added "on demand" as you create them. They are now persisted in some storage (disk, S3, google cloud, etc).
If you realize some variants are un-needed after all and change your code to not invoke them... I think they'll still be sitting persisted in storage.
How does one clean these up, so they're not taking up storage space? I can't find any ActiveStorage API to remove variants.

You can delete a file from ActiveStorage services (disk, s3 etc.) with its key . And a variant's key is identified by its blob and transformation. Therefore you can delete a specific variant like this:
avatar = user.avatar
variant = avatar.variant(resize: '100x100')
avatar.service.delete(variant.key)

If the cost of generating all variants again is acceptable or if you need to invalidate most variants, then you can simply delete the variants folder. Rails will generate the variants again when needed.

Related

Active Storage and Cloudinary : Using already uploaded images

In my seeds, I usually use Cloudinary and Active Storage by attaching new pictures to my object:
file = URI.open("https://my_image_location")
model_instance.photo.attach(io: file, filename: "file_name")
Problem is: each time we run the seed, a new upload of the image is done by Active Storage, and my Cloudinary account is filled with duplicate images.
I want to fix this problem by storing my images on Cloudinary, and making Active Storage use it directly without duplicating it, but I have no clue how to do that. (I was able to back in the days I was using CarrierWave, so it's a little frustrating :/)
Do you have any idea how to do that?
Thanks for your time!
Public id generation is handled by Active Storage, and thus you cannot choose the public id. This is one of the limitations of an Active Storage flow.
Since this is only for testing, you may be able to delete all the images from the database after your testing is done with a few commands in the rails shell.

Paperclip - Moving attachments from one S3 bucket to another

I have several paperclip attachments that live in one monolithic S3 bucket named foo
I want to split them up into several smaller, more logical buckets (foo1, foo2, etc...) based on some internal criteria.
I know which attachments need to move to which new buckets, and I've created the new buckets on S3 already.
Is there a good way to physically move the paperclip attachment to the new buckets programmatically using a rake task?
I can think of two options -
Loop through all attachments and download them temporarily to the filesytem, then re-upload them to the new bucket. This might be difficult on Heroku since there's no real local filesystem
Manually move the files on S3 while preserving the same folder structure. This is pretty laborious for hundreds of attachments though.
Thanks!

Carrierwave store method selection on-the-fly

Is there any existing solution to select store method on the fly in carrierwave?
I wish to select local store or fog (two providers) store on record (user) basis.
Do i have to rewrite my models to inherited models or there is other solution already?
Thanks for your thoughts.
You can access your model from uploader using the model method
To specify custom store dir, you can use
storage :fog
So, you can write your own macro-class-method which will call storage :for or local based on preference, should be possible but I don't know what you want to archieve exactly. Providing more code (The user code and the conditions on which storage depends) would be helpful.

Rails: What column type to use for saving uploaded images?

This is my first Rails project. I'm a bit stumped on how image files should be saved in the database, since they take up a lot of space. My site is going to be one where people upload a lot of images. In my migration for creating the pictures table, would I save the image file name as a string? Also does anyone have hints on where to save the images (assets, public, etc)?
Sorry, I'm just a noob looking for a little guidance.
You should consider storing your images on Amazon's S3 (or a similar alternative) instead of the database. You can use gems like paperclip to help you with uploading to a remote storage server.
However, if you really do want to store the binary image data in the database, then you probably want to use 'blob' as the column datatype.
You can also use carrierwave. Just create a string column and mount an uploader on it.
Blobs should only be used in special cases!
You save the images as files on a storage system on a server or the cloud. Then, you create a record in your table with the path to it.
Do not store an images byte for byte\BOLB.

Mananging upload of images to create custom pdfs on heroku - right tools

Im desiging an app which allows users to upload images (max 500k per image, roughly 20 images) from their hard drive to the site so as to be able to make some custom boardgames (e.g. snakes and ladders) in pdf formate. These will be created with prawn instantly and then made available for instant download.
Neither the images uploaded nor the pdfs created need to be saved on my apps side permanently. The moment the user downloads the pdf they are no longer needed.
Heroku doesn't support saving files to the system (it does allow to the tmp directory but says you shouldnt rely on it striking it out for me). I'm wondering what tools / services I should be looking into to get round this. Ive looked into paperclip, I'm wondering if this is right for this type of job.
Paperclip is on the right track, but the key insight is you need to use the S3 storage backend (Paperclip uses the FS by default which as you've noticed is no good on Heroku). It's pretty handy; instead of flushing writes out to the file system, it uses the AWS::S3 gem to upload them to S3. You can read more about it in the rdoc here: http://github.com/thoughtbot/paperclip/blob/master/lib/paperclip/storage/s3.rb
Here's how the flow would work:
I'd let your users upload their multiple source images. Here's an article on allowing multiple attachments to one model with paperclip: http://www.cordinc.com/blog/2009/04/multiple-attachments-with-vali.html.
Then when you're ready to generate the PDF (probably in a background job, right?), what you do is download all the source images to somewhere in tmp/ (make sure the directory is based on your model id or something so if two people do this at once, the files don't get stepped on). Once you've got all the images downloaded, you can generate your PDF. I know this is using the file system, but as long as you do all your filesystem interactions in one request or job cycle, it will work, your files will still be there. I use this method in a couple production web apps. You can't count on tmp/ being there between requests, but within one it's reliably there.
Storing your generated PDF on S3 with paperclip makes sense too, since then you can just hand your users the S3 URL. If you want you can make something to clear the files off every so often if you don't want to pay the S3 costs, but they should be trivial.
Paperclip sounds like an ideal candidate. It will save images in RAILS_ROOT/public/system/, which is both persistent and private (shouldn't be able to be enumerated on shared hosting).
You can configure it to produce thumbnails of your images if you wish.
And it can remove the images it manages when the associated model is destroyed - after your user downloads their PDF, and you delete the record from the database.
Prawn might not be appropriate, depending on the complexity of the PDFs you need to generate. If you have $$$, go for PrinceXML and the princely gem. I've had some success with wkhtmltopdf, which generates PDFs from a Webkit render of HTML/CSS - but it doesn't support any of the advanced page manipulation stuff that Prince does.

Resources