True Paperclip Replacement (Speficially Structure of the File System) - ruby-on-rails

With Rails 6, I need to replace Paperclip, but I can't find any substitutions that actually easily replicate it.
Specifically, the file structure paperclip used:
:model/:attachmant_field/000/000/000/:identifier/:style/:original_file_name
Over the last decade we have built several tools that rely on that structure (or something similar) and in addition our users expect that after uploading an image, they can reference the styles with the same file name and a permanent url (not a randomly generated name like ActiveStorage and Shrine does) and change the "style" component in the url to a different one in their html.
I've spent several days both on Shrine and ActiveStorage working to get the file structure and naming to work on and keep failing, as despite being "natural replacements" they don't actually handle things in the same way.
Our end system is on Amazon S3, though integrating with that hasn't been the issue, just the file system.
Thanks for your help, it's been really frustrating having to remove something that works great when there seems to be nothing that actually replaces it, if you want/need things done in the same way. I'd rather not have to start rewriting all of tools that we developed and resetting our customers expectations to work with a new structure.
Thanks so much.

Have you tried Carrierwave? You can specify any storage path and build it dynamically using model name (model.class.to_s.underscore), attachment field (mounted_as), model id (model.id). The original file name is also available as original_filename.

Related

Storing data inside a ruby gem, where / how to write files?

I've been working on a Ruby parser, that fetches data from different API sources, and compile this data into a clear read-to-use JSON file.
For my use case, i need to store the data i'm initially fetching from the different sources as i don't want to fetch them each time I use the code.
For now i'm writing the JSON i'm receiving from the API sources locally into different JSON files stored in a data folder where my ruby script is. Then i read those files again, parse them and generate my new formatted JSON file that i'm gonna use later in a Rails app.
For that matter i want to create a Gem from this ruby script, which i'm currently working on. Nevertheless i'm not sure to fully understand how and where i should store that data (the one i'm fetching and the one i'm generating).
For now i have tried to simply keep the code as is and simply try to write the file like so:
URI.open("path/to/where/i/wanna/store/file.json", "wb") do |file|
file << URI.open(fetched_data_url).read
end
But wherever i try to write the data i get a :
No such file or directory # rb_sysopen path/to/where/i/wanna/store/file.json
Which in a way does not surprise me that much as i expected it to work in different ways in the context of a Gem. But i'm still missing something here about how to handle this. I'm not sure to fully understand how that all works, especially when you use paths in a gem that will ultimately be used in a rails project.
So several questions here:
Whenever you use a path to write a file inside a Gem, is that path relative to the gem or to the project that will ultimately use that Gem? (and consequently will the file be written inside the project that uses the Gem?)
In that precise use case here, what should i do about it? Where and how do i store my data so that i can use it later? knowing that i need to store it as a JSON file and that for now any attempt of writing a file ends up with an error.
Any input on what i'm misunderstanding here would be much appreciated ! Thanks !
Whenever you use a path to write a file inside a Gem, is that path relative to the gem or to the project that will ultimately use that Gem?
There is nothing special about using file paths whether the code is part of a Gem or not.
path/to/where/i/wanna/store/file.json is a relative path, which means it is looked up relative to the current working directory of the user who started the script. That's nothing special about Gems, that's not even anything to do with Ruby. That is just how file paths work. Relative paths are relative to the current working directory, absolute paths are not.
Where and how do i store my data so that i can use it later?
This depends largely on the Operating System Environment. Different OS Environments have different conventions where to store what kind of files. E.g. your files look like they fit the definition of a cache and Windows has a dedicated folder for caches, as does macOS, as do Linux distributions that follow the Linux Standard Base, as do Desktop Environments that follow the Free Desktop Standards, as does Android, as does iOS, …
For example, the Free Desktop Group has the XDG Base Directory Specification, which defines directories for application state, application data, application cache, and many other things for XDG-compliant environments. Microsoft has similar specifications for Windows. The LSB has something to say as well.

Local file upload: File.open or StringIO

My application allows a user to upload an image and then create different versions of that image (e.g. aligned and cropped with another image). The intermediate step is that I need to copy the uploaded file to another object and process it. The easiest way to do this is to upload it locally.
From the carrierwave wiki, they suggest using a modified version of StringIO.
On the carreirwave readme, they also suggest using File.open (something like obj.image=File.open('path_to_file').
I've also found references to using fixture_file_upload from ActionDispatch::TestProcess (usually in testing, but I'm unsure why it is restricted to that environment).
Can anyone give me a good explanation on the pros and cons (if any) of using these methods?
Thanks.
I just discovered one major difference, at least in the context of carrierwave. If you use carrierwave with the move_to_cache option set to true and mount your upload column with File.open, the file given to File.open will be moved, while with StringIO, it won't.

Strategy for avoiding file upload naming conflicts

I have a webapp in Rails which as an AJAX file upload feature. Files are uploaded to a remote server (AWS S3). My current strategy is to upload the files in a temp/ directory (with their original name) until the user submits the form, and then rename them to their definitive name.
But the problem is that if multiple users try to upload two files with the same names at the same time, then one is gonna override the other.
The strategy I was thinking of to solve this was to generate random SHA1 when the upload page is loaded, store them in a table locally to make sure they're unique, and remove them when the temp file is renamed.
Do you see problems with this approach?
What's a good strategy to solve this problem?
One problem is, if they navigate away from the page without uploading anything, their hash will stay in the database, and eventually make a mess. I would avoid storing anything this temporary in the database.
Rather than try to come up with your own way to name temporary files, why not use the ruby tempfile library, which will do it for you?
Originally, I thought you were uploading the files to the ruby server, and uploading them to s3 yourself. Tempfiles won't help if users are uploading files directly. If you just want unique names for your temp files, a UUID generator might work for you. There is a Ruby UUID generator gem which is designed to not produce duplicates, even in a distributed setting. If you name your files with these, you shouldn't need to store anything in the database.

WYSIWYG image uploads in Rails App

Can anyone recommend a way of creating a view where users can upload images to my app through a WYSIWYG editor?
I've tried solving this using CK Editor and Paperclip but am having lots of trouble... Maybe I'm going about this the wrong way.
If someone's done this before I'd really like to know how! I don't have a editor or file storage mechanism preference so fire away...
This is all dependent on the WYSIWYG's file upload API. From there, just build an ImagesController to handle requests from that API, use whatever system (Paperclip is good) to handle those files internally, and you should be good to go. You won't find a plug-and-play solution; you'll have to hand-roll it.
Turns out that, with more targeted Google searching, you can find a preexisting solution. Here's one for TinyMCE and Rails. You may, however, end up finding that it doesn't meet your needs, in which case I would not be surprised to find that creating your own solution would be simpler than you expect :)
You could try Bootsy. It's a WYSIWYG editor with image upload capability. Includes a (rather simple) image manager as well.
https://github.com/volmer/bootsy
There is an other solution for rails out there:
https://github.com/spohlenz/tinymce-rails
You can load it as gem and configure it via a yml file. And it comes with an extra language gem.

rails + attachment_fu: issue with files in directories

I use attachment_fu for my rails app. It's great for me.
However, the designer who works with me complains about it because it saves files in different directory. She said that she can't handle those files efficiently with Photoshop as they are scattered.
I tried to persuade her with the following reasons.
We can avoid file name clash
It's faster than when they are in the same directory
But I couldn't convince her. How would you? Or are you with her? If so, why?
Sam
I think Adobe Photoshop has a built-in utility called 'Bridge' which allows easy asset management, might be worth having a look.

Resources