Downloading Rails Assets - File-paths In Development vs Production

社会主义新天地 提交于 2019-12-11 03:38:53

问题


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?


回答1:


Yes.

In /config/initializers create a file called say "config.yml" Set it up like so:

config.yml:

---
## NOT a tab character.  3 spaces.  (In case that affects you)                                                                                                                            
development:
   path_to_uploads: /path/to/downloads/for/development

production:
   path_to_uploads: /path/to/downloads/for/production

test:
   path_to_uploads: /path/to/downloads/for/test

Then create a file in the same directory (/config/initializers/) called config.rb

config.rb:

APP_CONFIG = YAML.load_file("#{Rails.root}/config/initializers/config.yml")

Hop over to your controller:

foo_controller.rb:

      class FooController < ApplicationController
           def download
              # ... 
              path_to_uploads = Rails.root.to_s + APP_CONFIG["#{Rails.env}"]['path_to_uploads'] 
## By handing it the Rails.env object, it will return the current environment and handle selecting the correct environment for you.
        end
    end

There is an excellent RailsCast on using YAML to find the environment here.

Hope that helps!




来源:https://stackoverflow.com/questions/18124673/downloading-rails-assets-file-paths-in-development-vs-production

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!