Use a fake DB adapter to avoid connection errors with rails assets precompile

If you've been using the rails asset pipeline for some time, chances are that you've run into one of these errors when trying to precompile the assets:

RAILS_ENV=production bin/rake assets:precompile  
=> rake aborted!
   FATAL:  database "..." does not exist
// PG::ConnectionBad: could not connect to server: Connection refused

Usually we would just go ahead and create the db, but this time we wanted to find a better solution since this was part of the build script from a docker image and we wanted to keep it simple.

A quick search on how to fix this points to this option on the initialization

config.assets.initialize_on_precompile = false  

This flag didn't help in our case, it was ignored on rails 4, since rails stopped trying to establish a connection on his own. Why is still failing then?

In our case the first culprit was the money_rails gem, which assumed that a connection was available, but it could've been any of the dozens of gems of the Gemfile.

A way go around this issue could be to add a dedicated environment with the minimum gems required for the app and the compilation process to work, but this can get cumbersome and break and go unnoticed until the next deploy / provision.

Here comes NullDB to the rescue! an ActiveRecord null database adapter designed to increase speed and isolation while testing.

From their docs:

NullDB is the Null Object pattern as applied to ActiveRecord database adapters. It is a database backend that translates database interactions into no-ops. Using NullDB enables you to test your model business logic - including after_save hooks - without ever touching a real database.

This fits our needs perfectly, we can take advantage of it to play nice with all those anxious gems while compiling our assets.

To use it we add the gem

# Gemfile

gem "activerecord-nulldb-adapter"  

We let the db adapter to be replaced with a env variable

# database.yml

production:  
  # this let us pass the 'nulldb' adapter when compiling assets
  adapter: <%= ENV['DB_ADAPTER'] ||= 'postgresql' %>
  # ....

And we pass it while compiling the assets:

# Dockerfile

DB_ADAPTER=nulldb bundle exec rake assets:precompile