如何将 Rails 引擎的 /public 文件夹复制到生产中的 Rails 应用程序?

How to copy over /public folder of Rails Engine to a Rails application in production?

我知道一个简单的解决方案就是手动将 Rails 引擎的 /public 文件夹中的所有文件复制到 Rails 应用程序的 /public 文件夹.但是,这意味着每次安装都需要手动复制。

此外,因为我的引擎使用的 Javascript 文件具有硬编码的图像路径,所以我不能简单地将所有静态文件都放在 app/assets 或 vendor/assets 下,因为那时 Rails 会将它们复制到 public/assets。我无法更改 Sprockets 输出文件的路径,因为我有其他 gem 希望它们的资产位于默认 public/assets 文件夹中。

我试过做类似

的事情
    class Engine < ::Rails::Engine
        if Rails.application.config.serve_static_assets
            initializer "static assets" do |app|
              app.middleware.insert_before(::ActionDispatch::Static, ::ActionDispatch::Static, "#{root}/public")
            end
        end
    end

但这只适用于开发。

就我个人而言,我认为最好的解决方案是更新您的 javascript 文件以遵循 Rails 的约定,将 javascript 中的硬编码图像替换为资产路径助手 - http://guides.rubyonrails.org/asset_pipeline.html#coding-links-to-assets 然后把所有东西都扔进 app/assets.

话虽如此,我可以想到您可能不想这样做的情况,这里可能就是这种情况。

根据您的 post,我猜您正在为生产预编译资产(即 - 运行ning rake assets:precompile)。在这种情况下,您可以挂接到 assets:precompile rake 任务并将文件复制过来。在你的引擎 lib/tasks/my_engine_tasks.rake:

中看起来像这样
Rake::Task["assets:precompile"].enhance do
  Rake::Task["my_engine:copy_assets"].invoke
end

namespace :my_engine do
  task :copy_assets => :"assets:environment"  do
    assets = ["file1", "file2"]
    assets.each do |asset|
      source_file = File.join(MyEngine::Engine.root, 'public', asset)
      dest_file = File.join(Rails.root, 'public', asset)
      FileUtils.copy_file source_file, dest_file, true
    end
  end
end

以上是简单的复制操作,但您也可以手动 运行 链轮处理这些文件。查看 assets:precompile 任务的代码(lib/sprockets/rails/task.rb in the sprockets-rails gem)和 Sprockets Manifest class(lib/sprockets/manifest.rb 在链轮 gem).