proper way to specify optional dependencies of a gem in ruby Gemfile
bundler, gemfile, ruby, rubygems, testing
Solution
Don't include the `a` gem in your dependencies, but `require` it anyway. If that fails, it will raise `LoadError`, from which you can rescue.
begin
require 'a'
rescue LoadError
# The 'a' gem is not installed
require 'b'
end
I believe this is the best way to use and test this setup:
Define an interface for your backend and allow a custom implementation to be easily plugged in.
module YourGem
class << self
attr_accessor :backend
def do_something_awesome
backend.do_something_awesome
end
end
end
Implement the `a` and `b` backends.
# your_gem/backends/a.rb
require 'a'
module YourGem::Backends::A
def self.do_something_awesome
# Do it
end
end
# your_gem/backends/b.rb
require 'b'
module YourGem::Backends::B
def self.do_something_awesome
# Do it
end
end
Set the one you want to use.
begin
require 'your_gem/backends/a'
Gem.backend = YourGem::Backends::A
rescue LoadError
require 'your_gem/backends/b'
Gem.backend = YourGem::Backends::B
end
This will use `YourGem::Backend::A` even if `b` is installed.
Before testing, make sure both `a` and `b` gems are installed, `require` both backends in the test code, run the tests with one backend, then run the tests again with the other backend.
Problem
a gem intends to support gems `a` or `b` as alternatives for a functionality. In code I check with `defined?(A)` if I fall back to `b` that's fine. But as a gem developer how to specify these dependencies? 1) what do I put in the Gemfile. ``` group :development, :test do gem 'a', :require => false gem 'b', :require => false end ``` This allows `Bundle.require(:test)` not to auto-require a,b? 2) How can explicitly require `a` and `b` separately to mimic (or mock) the scenario when we fall back to `b` in my tests? 3) Also how do I specify that either `a` or `b` is prerequisite for the gem. thanks