I have a downloads_controller.rb
with a single download
action which I want to trigger the download of a file that lives in a folder called downloads
which lives in a folder called download_assets
which I have added to my asset paths.
- download_assets [Added to asset paths]
- downloads
- file_1.pdf
- file_2.pdf
...
I can successfully access any files in the folder using:
http://my-app.dev/assets/downloads/file.pdf
In order to use send_file I need the file system path to this file rather than the URL. I can get the path the the root of my Rails project using Rails.root
, and the path to the file using asset_path(path)
. However, the problem is that because I'm in development, there is no file at this path. The file is stored in:
path/to/rails/project/app/assets/download_assets/downloads/file.pdf
The action:
def download
@download = Download.find(params[:id])
file_path = "downloads/#{@download.filename}.pdf"
file_path = "#{Rails.root}#{ActionController::Base.helpers.asset_path(file_path)}"
send_file(file_path, :type=>"application/pdf", x_sendfile: true)
end
To get this to work in development I need to use the following:
"#{Rails.root}/app/assets/download_assets/#{file_path}"
However this will fail in Production because assets will be precompiled and moved into assets
.
My current workaround is:
file_path = "downloads/#{@download.filename}.pdf"
if Rails.env == "development" || Rails.env == "test"
file_path = "#{Rails.root}/app/assets/download_assets/#{file_path}"
else
file_path = "#{Rails.root}{ActionController::Base.helpers.asset_path(file_path)}"
end
Is there an alternative to supplying a different path based on environment as this seems fragile?