Octothought

thinking about things from eight sides

Precompiling Assets for a Rails Engine on Heroku

I’ve been working on a project which is a Rails Engine and recently struggled through getting the engine’s asserts working within an app on Heroku. Because of how Heroku sets up the environment for the asset precompiliation step (or doesn’t set up the environment, as it happens), they recommend disabling the initialize_on_precompile setting (many apps are unable to complete their normal initialization without their Heroku environment config, which isn’t available during Heroku’s build process; turning off initialization during precompilation avoids that).

In your Rails application’s config/application.rb
1
config.assets.initialize_on_precompile = false

Once you do that, however, asset precompilation won’t trigger your Rails engine’s initialization, so even if you’ve set up your engine’s assets for precompilation as described in the Rails Engine Guide, your assets won’t actually get precompiled. Why? Because when initialize_on_precompile is disabled, only :assets initializers are run during precompliation.

The trick is to get Rails to run your engine’s initializer during asset precompilation even though it’s not actually initializing your whole application. The magic incantation for that is to pass a special :group => :assets or :group => :all option to your engine’s initializer, and make sure you configure your precompiled in that initializer.

In your Rails engine’s lib//engine.rb
1
2
3
4
5
6
initializer "RocketEngine asset precompile", :group => :all do |app|
  app.config.assets.precompile += %w(
    rocket.css 
    rocket.js
  )
end

Voilà!

I first got this working by specifying :group => :assets, but it turns out that :assets is only used during asset precompilation when initialize_on_precompile is explicitly disabled. So if you want your engine’s asset precompilation to work on other platforms as well as Heroku you should use :group => :all (which is special-cased to always run).

Comments