Axeman.IN

A Weblog of Programming, Philosophy and Random Thoughts.

Getting RefineryCMS' Asset Pipeline to Work With Heroku

The Problem

RefineryCMS’ assets somehow use the Rails URL helpers, which causes rake assets:precompile to throw error, which looks something like this:

Heroku Error
1
2
3
4
5
-----> Preparing app for Rails asset pipeline
       Running: rake assets:precompile
       rake aborted!
       undefined method `admin_dialogs_path' for #<Module:0x00000006d06708>
       (in /tmp/build_13ex2hfe5y1g5/vendor/bundle/ruby/1.9.1/gems/refinerycms-core-2.0.5/app/assets/javascripts/refinery/boot_wym.js.erb)

As suggested by comments on Issue #1751 of refinery/refinerycms one should have this:

config/application.rb
1
2
3
4
5
  RailsApp::Application.config do
    ....
    config.assets.initialize_on_precompile = false
    ....
  end

in his application.rb which means, on every deployment - compile the assets locally. Which is very inconvinient for any team which does atleast 2-3 QA deploys on an average day !

There is one more alternative given, which suggest use of heroku’s experimental user_env_compile which means environment will be loaded at the time of compilation. Which seems like an ok idea, but it is an experimental feature, so using that on production can be risky !

Additionally, if you set config.assets.initialize_on_precompile = true, you end up getting this error on heroku:

Heroku Error
1
2
3
4
5
6
-----> Preparing app for Rails asset pipeline
       Running: rake assets:precompile
       rake aborted!
       could not connect to server: Connection refused
       Is the server running on host "127.0.0.1" and accepting
       TCP/IP connections on port 5432?

But I’m not sure as why this error occured at all. But reagardless, I was not liking the approach to compile assets on every deployments.

The weird solution

Yes, the solution that I finalized was weird and I’m still not onboard with the idea which I’m going to discuss.

I decided to investigate options with not having to compile assets locally on each deploy. If you look at the error it says it cannot find some path which is being acccessed from some erb. I decided to somehow load the refinery engine routes at the compile time. And to do that very shamelessly I begged Google for help, and as most of the times Stack Overflow came to rescue :-)

The first answer to this question was basically something that enlightened me.

Here is the snippet from the answer:

config/application.rb
1
2
3
4
5
6
7
8
module AssetsInitializers
  class Railtie < Rails::Railtie
    initializer "assets_initializers.initialize_rails",
                :group => :assets do |app|
      require "#{Rails.root}/config/initializers/load_config.rb"
    end
  end
end

As the question was about loading SOME initializer while compiling assets, this code just loads the load_config.rb.

We on the other hand want to load a file (config/routes.rb) which is inside refinerycms code.

We can’t directly require the file, as it is not in lib folder of the refinerycms-core gem

So after browsing through some refinerycms code, I found out a method Refinery::Core.root which gave me the full path to root of refinerycms-core gem (Not the /path/to/all/gems/refinerycms-core-2.0.10/lib, which is loaded in load_path by Bundler.require)

So finally I ended up doing this:

config/application.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
module RailsApp
  class Application < Rails::Application
    ....
    config.assets.initialize_on_precompile = false
    ....
  end
end

module AssetsInitializers
  class Railtie < Rails::Railtie
    initializer "assets_initializers.initialize_rails",
                :group => :assets do |app|
      Devise.warden_config = Warden::Config.new
      require "#{Refinery::Core.root}/config/routes"
    end
  end
end

We need that devise line to make sure devise has a warden_config object, otherwise now devise starts throwing exceptions !

But remember again, this is just hack, if you ever find out a better enough solution, please drop me a mail or just comment down here.

Comments