Yes, your approach should work, as Ruby's gem resolution system will prefer a locally vendored gem if it is available before falling back to fetching and installing the remote version. Here's a step-by-step guide on how to accomplish this:
You can create an empty gem with the same name as the gem you want to "erase." Here's how to do it:
Generate the empty gem:
bash
bundle gem erased_gem_name --skip-test --skip-git --skip-coc --skip-ci
Replace erased_gem_name
with the name of the gem you want to override.
Update the gemspec file:
erased_gem_name.gemspec
to have only the minimal requirements.ruby
Gem::Specification.new do |spec|
spec.name = "erased_gem_name"
spec.version = "0.0.1"
spec.summary = "An empty gem to override the real one."
spec.authors = ["Your Name"]
spec.email = ["[email protected]"]
spec.files = []
spec.license = "MIT"
end
Build the gem:
bash
gem build erased_gem_name.gemspec
Vendor the gem into your project:
vendor/gems
directory (or similar) in your project, and copy the generated gem file into this directory.Gemfile
Update your Gemfile
to point to your vendored gem:
ruby
gem 'erased_gem_name', path: 'vendor/gems/erased_gem_name-0.0.1.gem'
In your Gemfile
, specify your "erased" gem as a direct dependency so it satisfies the constraints of the transitive dependency.
For example, if you have a gem expensive_gem
which is included as a transitive dependency and has a constraint like >= 1.0
, make sure your vendored erased_gem_name
meets that constraint. You can adjust the version number in the gemspec if necessary.
ruby
gem 'expensive_gem', '>= 1.0', path: 'vendor/gems/erased_gem_name-0.0.1.gem'
Run bundle install
to make sure the dependency is correctly overridden:
bash
bundle install
Then verify that bundle show
or bundle list
points to your vendored gem instead of the remote gem.
LoadError
or NoMethodError
exceptions in such cases.This approach is suitable if the goal is simply to skip installing the remote gem and its dependencies while avoiding breaking the dependency graph.