Search code examples
rubydependenciesrubygemsrequire

Optional runtime dependency for Ruby gem with executables


I'm writing a gem aipp which exposes a few executables, nothing fancy here:

#!/usr/bin/env ruby
require 'aipp'
AIPP::NOTAM::Executable.new(File.basename($0)).run

Parts of the gem optionally use database adapters (pg or ruby-mysql gem). But since these can be a pain in the butt when the gem is used on the cloud, I'd like to really make them optional and not require them as runtime dependency in the .gemspec.

So I require them conditionally at runtime:

require 'pg' if ENV['AIPP_POSTGRESQL_URL']
require 'mysql' if ENV['AIPP_MYSQL_URL']

Unfortunately, that doesn't work as expected. When either of the environment variables is set and the executable is used, the require fails – probably because there's no dependency declared.

I've tried an inline Gemfile on the executable like the following. Works in development (repo checkout), but not when the gem is intalled via Rubygems:

#!/usr/bin/env ruby
require 'bundler/inline'
gemfile do
  source 'https://rubygems.org'
  gem 'aipp'
  gem 'pg', '~> 1' if ENV['AIPP_POSTGRESQL_URL']
  gem 'ruby-mysql', '~> 3' if ENV['AIPP_MYSQL_URL']
end
AIPP::NOTAM::Executable.new(File.basename($0)).run

What's the correct approach to require gems which are not listed as runtime dependency but installed additionally (via gem install or Gemfile)?

Maybe somebody knows of an existing gem which has already solved this problem somehow.

Thanks for your help!


Solution

  • I would use bundler groups for that.

    gemfile do
      source 'https://rubygems.org'
      gem 'aipp'
      group :database do
        gem 'pg', '~> 1'
        gem 'ruby-mysql'
      end
    end
    

    There is more info about how to use them in the link.