ruby / ruby/rubygems

Feature Request: Optional dependency version specifier

Open
#1,811 32 comments 36 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

help wanted status: ready type: feature request
Dominant language
Ruby
Stars
4k
Forks
1.9k
Avg merge
1d 2h
Merged PRs (30d)
81

Description

I would like to suggest a feature.

My current problem is when developing a gem with "optional" dependencies there is no way to tell rubygems a valid gem version specification.

For example in Sprockets we have optional code that can be run if you have uglifier gem on your system. However not all users of Sprockets wish to use Uglifier so we do not want to depend on it in the gemspec. Recently there was a breaking change in the Uglifier API, if we were directly depending on this gem then I would solve the problem by only allowing users with uglifier >= 3.0.4 with Sprockets 4. However since we are not declaring this as a dependency, there is no way to do this.

I am proposing a declaration in the Gemspec like this:

  s.optional_dependency "uglifier", ">= 3.0.4"

Proposed behavior: If this was in a gemspec then if the Sprockets gem is loaded first, then when the Uglifier gem will be subject to the additional version specification. If the Uglifier gem is loaded first then the system would error out while trying to load Sprockets if it is not within the specification. Ideally if bundler could eventually integrate to resolve optional dependencies at install time, that would be 👌.

Current behavior: Right now the only way to handle the case is to branch as in this PR https://github.com/rails/sprockets/pull/448 or to manually detect versions at runtime and error out. Proposed behavior would make the case where sprockets is required first much better, while the other case of uglifier loaded first would be essentially the same (loadtime/runtime error). Eventual ability to coordinate with bundler would be the ultimate end goal.

I see this as beneficial for a wide range of gems:

  • multi_json: supports many json backends but does not depend on ALL of them being loaded to work, just one.
  • active_record: supports many database backends but does not depend on ALL of them being loaded to work, just one.
  • Sprockets as mentioned
  • The sentry client raven maintainer mentioned they have optional gems.
  • etc.

This is a pretty significant feature proposal/request. I'm curious what you think of the overall idea as well as any currently available alternatives that don't require a feature in rubygems that I've not already touched on.

I will abide by the code of conduct.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Review the proposed optional_dependency API and the referenced Sprockets pull request 448 first. Trace how gemspec dependency declarations currently work and consider the load-order and version-enforcement behavior described in the issue. Done requires an agreed API and behavior for optional dependencies, including whether Bundler should eventually resolve them.

Written by the indexing model from the issue text.

Assessment

Tech stack
ruby
Domain
tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.