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 = ["you@example.com"]
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.GemfileUpdate 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.