Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I know a simple solution would be just to manually copy over all the files in the Rails Engine's /public folder to the Rails application's /public folder. However, this means that each installation would require manually copying.

Furthermore because the Javascript files that my engine uses have hard-coded image paths, I cannot simply throw all my static files under app/assets or vendor/assets, as then Rails would copy them over to public/assets. I can't change the path where Sprockets outputs the files as I have other gems that expect their assets to be in the default public/assets folder.

I tried doing something like

    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

but this only works for development.

like image 450
Kent Shikama Avatar asked Oct 19 '25 16:10

Kent Shikama


1 Answers

Personally, I believe that the best solution would be to update your javascript files to follow Rails' conventions by replacing the hard-coded images in the javascript with the asset path helper - http://guides.rubyonrails.org/asset_pipeline.html#coding-links-to-assets and then throwing everything into app/assets.

With that said, I can think of situations where you may not want to do that, and that may be the case here.

From your post, I'm guessing that you're precompiling assets for production (i.e. - running rake assets:precompile). In that case, you can just hook into the assets:precompile rake task and copy the files over. It would look something like this in your engine's 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

The above is a simple copy operation but you can also manually run sprockets over those files as well. Take a look at the code for the assets:precompile task (lib/sprockets/rails/task.rb in the sprockets-rails gem) and the Sprockets Manifest class (lib/sprockets/manifest.rb in the sprockets gem).

like image 186
Jongyu Lin Avatar answered Oct 21 '25 05:10

Jongyu Lin