carlhuda/bundler — Issue #1636: Please support conditional gems
Author: FooBarWidget
Created: 2012-01-19 21:08:54+00:00
State: open

Some people are writing apps that are not only meant to be used internally, but also by the general public. Think RedMine. These apps typically allow the user to choose their database driver through `config/database.yml`. However the driver must also be specified inside Gemfile, otherwise the app cannot load it. The result is that the user has to edit both database.yml and Gemfile, which introduces the following problems:

* The user may not necessarily be a Ruby programmer. The Gemfile will confuse him.
* The user is not able to use the `Gemfile.lock` that the developer has provided. This makes installing in deployment mode with the developer-provided Gemfile.lock impossible.

This can be worked around in a very messy form with groups. For example:

group :driver_sqlite do
gem 'sqlite3'
end

group :driver_mysql do
gem 'msyql'
end

group :driver_postgresql do
gem 'pg'
end

And then, if the user chose to use MySQL:

bundle install --without='driver_postgresql driver_sqlite'

This is messy because you have to exclude all the things you don't want. If the app supports 10 database drivers then the user has to put 9 drivers on the exclusion list.

I propose supporting conditionals in the Gemfile language. Example:

condition :driver => 'sqlite' do
gem 'sqlite3'
end

condition :driver => 'mysql' do
gem 'mysql'
end

condition :driver => 'postgresql' do
gem 'pg'
end

condition :driver => ['mysql', 'sqlite'] do
gem 'foobar'
end

The following command would install the `mysql` and the `foobar` gems:

bundle install --condition driver=mysql

Here, Bundler *must* enforce that the `driver` condition is set; if it's not set then it will raise an error. To allow for the `driver` condition to not be set, the developer must explicitly define that the condition may be nil:

condition :driver => nil do
gem 'null-database-driver'
end

Here, `bundle install` will install `null-database-driver`.