active storage / clean files url - ruby-on-rails

Multiple question around the same issue, the way active storage returns file urls
For now with the default setup, the following (cloud or local), returns somehow the following :
_domain/_path/_superlong_hash/_original_filename._ext
Given paperclip or many other existing gems, the _path/_superlong_hash/_original_filename._ext part is in hand to be customised, could end up in a clean url for any files
Meaning by that :
is there a way to "proxy" the _path with something more custom ?
is there a way to avoid the _superlong_hash ?
is there a way to customize the filename on the fly (or on uploads) ?
To make it a one-liner, how one would customize the files urls ?
I've seen here and there people ending up creating custom controllers to serve file with decent urls, but let's admit this is a no go (IMHO)

I hope that ActiveStorage proves me wrong soon, but at the time of writing Rails 5.2, the straight answer seems to be that you have to go with your 'no go' option, hacking your own controllers together and heavily patching ActiveStorage to expose files.
For proxying see:
https://github.com/rails/rails/issues/31419
https://github.com/rails/rails/pull/30465
especially georgeclaghorn responses are interesting
For renaming file:
#user.avatar.blob.update(filename: 'NewFilename.jpg')
Manipulating the _superlong_hash / url
I have no good answer for this one. Although ActiveStorage makes it breathtakingly easy to upload (and somewhat easy to manipulate) files it takes Rails opinionated software philosophy to the edge, making it quite difficult to bypass it's obscurity by abstraction approach to url generation. ActiveStorage provides no built-in methods to do rudimentary things like permanent or direct links to files and variants once generated. File/image caching and nice urls seem therefore not to be possible to accomplish out of the box with ActiveStorage at this point in time.

Related

Organise Active Storage files for use in other systems?

Active Storage stores uploads in a file structure like so:
This is great if the rails app is the only software that needs to use these files.
But what if the app simply serves as a means to upload the images to S3 so that some other (completely separate) service can consume them?
The problem being, other developers wouldn't be able to make any sense of the directory and files, since they're labelled in a way rails can understand, but which a human cannot (e.g. what does folder named "O2" mean?).
Is there some way to ensure uploads are stored in a human-friendly way? e.g. each folder could be a user_id, with their assets inside? (or similar)
As far as I remember, you would have to implement an own service that somehow replace the key used to something else (e.g. S3Service), or patch ActiveStorage to create the key itself in a different way. I am not sure that this would suffice though, as the key is most likely used for other critical functionality outside of the Service.
Alternatively you might poke in ActiveStorage::Blob to fiddle with the key. That said, ActiveStorage does not support what you'd like out of the box and you would have to take the risk of messing with its internals.
A solution to the problem (but not answer to you question) might be implementing an API as outlined in the comments to your question.

What is the simplest Rails file upload method?

I've looked at the available options and it seems like everything is optimized for image uploading as display. I just need simple file upload and retrieval. Are there any good options?
Paperclip is a popular choice for uploading and sizing images, but you can upload any type of file with it (doc, zip, txt, pdf... anything). Highly recommended. https://github.com/thoughtbot/paperclip
I like carrierwave. It has built in support for s3, has no workaround for setting up apps on heeroku unlike paperclip.
I use Carrierwave for mine and have been happy with it. I am just uploading general files, not specifically images. It is easy to implement and has good advanced features if you need them later. It also integrates with Fog to make using remote storage sources (like s3 or rackspace cloud files) easy.
Carrierwave benefits:
With carrierwave, the attachment is a seperate model instead of an attribute on an existing model, which might make things cleaner to work with.
It comes with the ability to attach a file via url (user passes in a url to a file) instead of uploading with a form).
It comes with some sort of way to remember files across form validation failures, although I've never used this and I'm not sure how it's done... maybe with two forms and ajax?
It seems to have a more engaged and enthusiastic community around it, with more projects extending it.
For S3, they use fog instead of aws-s3, and fog has much more active development.
That said, paperclip is pretty great and is actively maintained, and might come with handier default image manipulation stuff, I'm not sure.

Rails how to edit and save files in browser?

I want to make a CMS where I can edit the view and css files online in my browser.
How can it be done? Does everything have to be in a database?
Generally Stack Overflow is not for research, it's for problem solving. That said…
No, your editable assets do not have to be in a database for this to work.
But you want them to be anyways; allowing write access to the files in your application isn't the best approach.
The rendering chain of Rails 3 allows you to sub in your own view parser and add a path to the built in view-finding that you can trick into loading from a database relatively easily.
Having your end users write in something like Liquid templates will save you a lot of work and allow this to happen with relative ease. They won't have access to unsafe Ruby methods, and you won't have to go through all the work of sandboxing them in Ruby.
CSS has fewer security implications, so you can fairly easily store raw CSS in the database and allow your users to edit it to their liking and then serve it up with a request to a stylesheets/:user_id/style.css request (with some heavy caching, like with Varnish, to save your application from being murdered).
Hopefully that'll get you started out in the right direction. If you decide to hook into the rendering stack in Rails I strongly suggest you pickup a copy of Crafting Rails Applications — one of the handful of example applications it walks you through does just that at a fairly granular level.

Django, Rails Routing...Point?

I'm a student of web development (and college), so my apologies if this comes off sounding naive and offensive, I certainly don't mean it that way. My experience has been with PHP and with a smallish project on the horizon (a glorified shift calendar) I hoped to learn one of the higher level frameworks to ease the code burden. So far, I looked at CakePHP Symfony Django and Rails.
With PHP, the URLs mapped very simply to the files, and it "just worked". It was quick for the server, and intuitive. But with all of these frameworks, there is this inclination to "pretty up" the URLs by making them map to different functions and route the parameters to different variables in different files.
"The Rails Way" book that I'm reading admits that this is dog slow and is the cause of most performance pains on largish projects. My question is "why have it in the first place?"? Is there a specific point in the url-maps-to-a-file paradigm (or mod_rewrite to a single file) that necessitates regexes and complicated routing schemes? Am I missing out on something by not using them?
Thanks in advance!
URLs should be easy to remember and say. And the user should know what to expect when she see that URL. Mapping URL directly to file doesn't always allow that.
You might want to use diffrent URLs for the same, or at least similar, information displayed. If your server forces you to use 1 url <-> 1 file mapping, you need to create additional files with all their function being to redirect to other file. Or you use stuff like mod_rewrite which isn't easier then Rails' url mappings.
In one of my applications I use URL that looks like http://www.example.com/username/some additional stuff/. This can be also made with mod_rewrite, but at least for me it's easier to configure urls in django project then in every apache instance I run application at.
just my 2 cents...
Most of it has already been covered, but nobody has mentioned SEO yet. Google puts alot of weight on the URL itself, if that url is widgets.com/browse.php?17, that is not very SEO friendly. If your URL is widgets.com/products/buttons/ that will have a positive impact on your page rank for buttons
Storing application code in the document tree of the web server is a security concern.
a misconfiguration might accidentally reveal source code to visitors
files injected through a security vulnerability are immediately executable by HTTP requests
backup files (created e.g. by text editors) may reveal code or be executable in case of misconfiguration
old files which the administrator has failed to delete can reveal unintended functionality
requests to library files must be explicitly denied
URLs reveal implementation details (which language/framework was used)
Note that all of the above are not a problem as long as other things don't go wrong (and some of these mistakes would be serious even alone). But something always goes wrong, and extra lines of defense are good to have.
Django URLs are also very customizable. With PHP frameworks like Code Igniter (I'm not sure about Rails) your forced into the /class/method/extra/ URL structure. While this may be good for small projects and apps, as soon as you try and make it larger/more dynamic you run into problems and have to rewrite some of the framework code to handle it.
Also, routers are like mod_rewrite, but much more flexible. They are not regular expression-bound, and thus, have more options for different types of routes.
Depends on how big your application is. We've got a fairly large app (50+ models) and it isn't causing us any problems. When it does, we'll worry about it then.

URL Etiquette: can all my urls end with .php?

Given my new understanding of the power of "includes" with PHP, it is my guess that ALL of my pages on my site will be .php extension.
Would this be considered strange?
I used to think that most pages would be .htm or .html, but in looking around the net, I am noticing that there really isn't any "standard".
I don't really think I have a choice, if I want to call my menus from a php file. It is just going to be that way, far as I can see... so just bouncing off you all to get a feel for what "real programmers" feel about such issues.
The thing that actually matters to the browser isn't the file's extension; it's the MIME Type that it gets sent in the HTTP headers. Headers are data that gets sent before the actual file and tell what kind of data it is, how big it is, and a bunch of other unimportant junk. You can configure your server to send any file extension as an HTML page, but the most common extensions for HTML pages are .htm, .html, .php, .asp, .aspx, .shtml, .jsp, and several others.
As for it looking "strange", a surprisingly small number of users will actually look at the address bar at all, let alone notice that the file extension is .php instead of .html. I wouldn't worry about it if I were you; it really doesn't make a difference.
generally - make sure your URLs are easily read, reflect the content beneath them, and don't change. the "not changing" part can be tricky, especially when you shift technologies over time (html>php>aspx).
to achieve this just ensure that each area of your site appears to reside in its own subdirectory.
mysite.com/news/
mysite.com/aboutus/
mysite.com/products/
etc.
you can either do this by physically structuring your site in this fashion and using default documents (default.html/php/aspx), or using something like mod rewrite, ISAPI rewrite, or similar to rewrite these paths to the appropriate docs.
someone who's keen on SEO or marketing might have a different idea about what constitutes a "good" URL, but as a developer this is how i see it.
Ending URLs in .php is fine technically, but I think these days many people are trying to make the urls independent of the actual code/file structure.
I actually think that's a good thing from a software engineering perspective as well. URLs are conceptually different (read: not related at all) to the file/directory structure used to organize the system powering the website.
The "resource" that a URL "locates" is not the .php or .asp file that contains the code to display it.
Look at stackoverflow for example, the URL of this question is /questions/322944/uql-etiquette, there's nothing in it that can be used to "guess" the underlying framework/system. The resource in this case is the question and all the answers to it, as well as the comments, votes, edits, and various other stuff.
It doesn't matter what your URLs end with, .php is fine, and fairly common. The only thing people care about these days when it comes to URLs is making them pretty for Search Engine Optimisation, but that's a whole new question.
Real programmers use URLs like /noun/verb/id/ & don't show file extensions at all :p
Personally I use Apache's mod-rewrite.
(on a slightly less tongue-in-cheek note) It's worth mentioning, specifically for includes, that you should ensure your actual files have the extension .php. I've seen more than one site where programming logic can be viewed in-browser 'cos the developer ended their files .inc (or insert non-auto-parsed extension of choice here).
As far as url etiquette goes - I really don't think etiquette is involved; however if you have sophisticated users visiting your website who have strong views on platforms and technologies, using .php or .aspx extensions could put off users - perhaps subconsciously.
If you use apache, it's fairly easy to make a .php be read as a .py and vice versa by changing the httpd.conf file. My current practice is to use .html extensions (or no extensions at all) and treat all files as .php.
Whatever you decide, do make sure that you never break an existing url. It's possible to achieve that even if you keep .php as the extension and decide to change the technology later.

Resources