资产管道——如何将Rails引擎的/公共文件夹复制到生产环境中的Rails应用程序



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

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

我试着做一些像

    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的惯例,用资产路径助手- http://guides.rubyonrails.org/asset_pipeline.html#coding-links-to-assets替换javascript中的硬编码图像,然后将所有内容放入app/assets。

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

从你的帖子,我猜你是预编译生产资产(即-运行rake资产:预编译)。在这种情况下,您可以直接钩入资产:预编译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

以上是一个简单的复制操作,但您也可以手动运行这些文件的链轮。看看这些资产的代码:预编译任务(lib/sprockets/rails/task)。Sprockets Manifest类(lib/Sprockets/Manifest . b)和Sprockets Manifest类。

似乎Rails没有提供一种明显的方式来从引擎中提供静态资产。这就是我对这个问题的动态解决方案。

module MyApp
  class Engine < ::Rails::Engine
    isolate_namespace MyApp
    initializer "my_app.assets.precompile" do |app|
      app.config.assets.precompile << "my_app_manifest.js" ### manifest file required
      ### Precompile all static assets
      ### Note in this example use a non-standard folder (app/assets/public/)
      ["app/assets/images/", "app/assets/public/"].each do |folder|
        dir = app.root.join(folder)
        if Dir.exist?(dir)
          Dir.glob(File.join(dir, "**/*")).each do |f|
            asset_name = f.to_s
              .split(folder).last # Remove fullpath
              .sub(/^/*/, '') ### Remove leading '/'
            app.config.assets.precompile << asset_name
          end
        end
      end
    end
  end
end

最新更新