Here is what I would like to achieve. Given a model that has something like this
class MyModel < ApplicationRecord
has_many_attached :files
end
I would like to be able to serve the attachments as files under
GET /mymodels/:id/files/:filename
(filename includes the format as well).
Of course this assume that my application no duplicate filenames for a specific MyModel id.
Is there a specific way that is recommended to do that?
config/routes.rb
fully supports non-resourceful routes (i.e., arbitrary URL). They support dynamic segments in a form like in your question:
get '/mymodels/:id/files/:filename', to: 'mymodels#serve_file'
Given the above route, hitting https://my_app.com/mymodels/1/files/banana.txt
will send the request to to the show_files
method on MyModelsController
with params of:
{ id: 1, filename: 'banana.txt' }
The Rails Guide has lots of documentation for non-resourceful routes.
EDIT: (the gist of the question was clarified)
If your intent is to automatically download the attached files when the URL is hit, your controller action might look like:
def serve_file
mymodel = MyModel.find(params[:id])
blob = mymodel.files.blobs.find_by(filename: "#{params[:filename]}.#{params[:format]}")
redirect_to blob.url
end
You have to reconstitute the filename, since Rails will automatically split the terminating element in a path into filename
and format
parameters.
NB: I had some trouble in dev with :local
storage getting .url
to work, but this works fine with actual remote storage (S3, etc.).
If your intention is to display/manipulate the file within your app (i.e., not download), you should consider passing the filename as a query parameter rather than have it as the terminating element in the URI.