It most cases it's not necessary to add a version constraint next to your gems in the Gemfile. Since all versions are saved in the Gemfile.lock, everyone running bundle install will get exactly the same versions.
There are some exceptions, where you can consider adding a version constrain to the Gemfile:
- You are not checking in the
Gemfile.lockinto the version control (not recommended) - A specific gem has a bug in a more recent version (adding a comment for the reason is highly recommended)
- You want to ensure no one upgrades a library with
bundle update
An drawback of this approach is, that adding new gems might also upgrade existing gems. So check your Gemfile.lock carefully when submitting a commit. Note that the approach in this card works best, if you use bundle outdated together with bundle update some_gem --convervative for major updates, before running bundle update on all minor and patch updates.
Examples
Bad
source "https://rubygems.org"
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
ruby "2.7.6"
gem "rails", "~> 7.0.6"
gem "sqlite3", "~> 1.4"
gem "puma", "~> 5.0"
- This blocks automatic updates of
rails,sqlite3andpumawithbundle update
Note: bundle add will automatically add ~> with the current version of the new gem and you need to take care to remove this version constraint afterwards again.
Good
source "https://rubygems.org"
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
ruby "2.7.6"
gem "rails"
gem "sqlite3"
gem "puma"
- All gems are easily updateable with
bundle update
Good
source "https://rubygems.org"
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
ruby "2.7.6"
gem "rails", "~> 7.0.6"
gem "sqlite3"
gem "puma"
-
bundle updatewill never perform a majorrailsupdate unless you change this line
Okay
source "https://rubygems.org"
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
ruby "2.7.6"
gem "rails"
gem "sqlite3", ">1.4.0" # CVE-XYZ
gem "puma"
- Downgrades with bundler happens only in rare cases and will emit a warning
Note: some_gem version regressed from a to b. Checking theGemfile.lockcarefully when submitting a commit should be good enough to prevent reintroducing previous issues. - If you have big concerns, that a downgrade might reintroduce a security issue again, you still might add this contraint
- On the other hand, if you consequently enforce this, your rails line would have a long line of comments with CVEs
Good
source "https://rubygems.org"
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
ruby "2.7.6"
gem "rails"
gem "sqlite3"
gem "puma", "<5.0" # Puma 5.0 does not work with our HMR middleware yet (see story #1234)
- Preventing upgrades in case the newest version has a bug or is for some reason not working within the project