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

Ken*_*ama 4 ruby-on-rails bundler asset-pipeline

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

此外,因为我的引擎使用的 Javascript 文件具有硬编码的图像路径,所以我不能简单地将所有静态文件放在 app/assets 或供应商/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
Run Code Online (Sandbox Code Playgroud)

但这仅适用于发展。

小智 5

就我个人而言,我认为最好的解决方案是更新您的 javascript 文件以遵循 Rails 的约定,方法是用资源路径助手替换 javascript 中的硬编码图像 - http://guides.rubyonrails.org/asset_pipeline.html#编码链接到资产,然后将所有内容放入应用程序/资产中。

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

从您的帖子中,我猜测您正在预编译用于生产的资产(即运行 rake asset:precompile)。在这种情况下,您可以直接连接到 asset: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
Run Code Online (Sandbox Code Playgroud)

以上是一个简单的复制操作,但您也可以在这些文件上手动运行 sprocket。查看 asset:precompile 任务(sprockets-rails gem 中的 lib/sprockets/rails/task.rb)和 Sprockets Manifest 类(sprockets gem 中的 lib/sprockets/manifest.rb)的代码。