May "bundle install" update gems for rails application? - ruby-on-rails

My bundle file contains gem descriptions like:
gem 'turbolinks', '~> 5'
gem 'kaminari'
During the lapse of one year, these gems were updated, losing backward compatibility. After that, if I run bundle install in a new machine that has no gems, I fear it will install all gems with the latest versions, and my code will break due to this.
Am I right? what is the solution to avoid this issue?

I fear it will install all gems in latest versions and my code will break due to this.
If you've Gemfile.lock along with Gemfile bundle install doesn't break your code. The Gemfile.lock file is where Bundler records the exact versions that were installed (or must be installed). Otherwise you might have problems with versions dismiss.

Related

bundle install does not respect Gemfile.lock

I faced some issues with bundle install.
When we run 'bundle install' , One of the dependency gem in Gemfile.lock is get auto upgraded.
As per theory, "bundle install" will look the Gemfile.lock for version and won't resolve the version and will install the same versions. It will resolve only when there is no Gemfile.lock or when we give "bundle update".
In our server, we having Gemfile.lock but "bundle install" is updated the particular gem mentioned gemfile.lock(it's a dependency gem , so we not specified in gemfile), It should not happen like this, because already one version present in lock file, even though that version is get auto updated, Due to this upgrade some major functionality is broken in the site.
For your references:
bundler version - 1.17.2
ruby version - 2.5.3
gem version - 2.7.6
rails version - 5.2.3
that dependency gem name is "nokogiri", This gem locked as 1.11.7, But it's updated to "1.12.1" when i give "bundle install"
Any idea to prevent this issue in future?
First of all it'll be great if you shared the Gemfile.lock error so as to know what i particular might be causing that upgrade. But from afar I think as you said this gem is a dependency gem and it is not stated in your gemfile. It could be that another gem also depends on this gem and per that requirement it triggers an upgrade even before your supposed gem line is run which may be leading to the error. Read the error thoroughly and you can identify the gem(s) causing this.
After your update I have read around on this.
Exactly so as stated earlier on, one of these gems could be the reason why your particular gem gets updated with every bundler install. Unfortunately there is no true turn around to solving this but bundler does give a way around.
You can use the --frozen option with bundler which freezes your gemfile.lock to the current versions for each gem and does not update any gem but only installs new gems that you have. Unfortunately this has been deprecated and can only be done be done from /.bundle/config. This can be done from the command line in the root of your project.
run
bundle config frozen true to freeze bundler from updating your gems in gemfile.lock
You may have to grant write permissions to your user to be able to edit the bundle configurations.
I found this article as well from bigbinary.com

Is there a way to get a gem's version before running bundle install (from Gemfile.lock)

I want to get a Gem's version without running bundle install.
Which is to say I want figure out what version bundle is planning to install without actually installing the gem.
Say read it from the Gemfile.lock(and Gemfile) combined.
Is there a way I can resolve what version bundler plans to install?
I need this because I want to cache the expensive installs while running docker build.
Gems like rails(nokogiri) take a while to install and I would like to do gem install rails -v ... in a previous step before running bundle install.
For this purpose i need to get the rails version before hand
If you add a new gem to your gemfile, but don't do bundle install, it doesn't install yet. Instead, you can run bundle lock, which generates a new lock file. This includes the gem version of the new gem that would be installed.
By running bundle show new_gem, it shows it isn't actually installed.
To be sure maybe get a backup of the original Gemfile.lock before running the command though.
By default if no version is specified in the Gemfile, running bundle install will attempt to install the latest version of the gem which is compatible with the rest of the gems and ruby version in your project. This will create a Gemfile.lock file if one doesn't already exist. If a Gemfile.lock file is already committed to git repo, it should then install the versions specified in Gemfile.lock. The point of bundler is to handle dependencies to insure your stack works correctly.
To see the version of a gem bundler is currently using you can run
bundle show rails
You will probably want to specify the ruby version in the Gemfile for example
ruby '~> 2.5' #
You can specify exact version of a gem in the Gemfile like this which you should be able to rely on to be the version bundler will install so long as it's compatible with the rest of the stack. bundle install will throw errors if there are incompatible gem versions.
gem 'rails', '4.2.11' # this will always install only this version.
You may also use pessimistic operator (~>) to set for only minor updates
gem 'influxdb', '~> 0.6.1' # could go to 0.6.2 but never 0.7.0
You can also set minimum versions like this although it's probably not what you need for your question.
gem 'pg_query', '>= 0.9.0'
If you have a Gemfile.lock already in your repo you can see which version would be installed by running for example:
gem show rails
Which would show you the version and weather it or not it is currently installed.
For more info see bundle --help

Running a ruby on rails app locally - Different versions of ruby

I'm using RVM to manage the different ruby versions I have. One particular application is using an older ruby version (2.3.1), and I've noticed that, once I've changed to that version and run rails server on it, it doesn't work because I'm required to change a whole cascade of Gems or other files, such as nokogiri, to make it run.
Generally, from what I've read online, I should just do a simple bundle install to do all of this before running rails server. However, it doesn't work as there are more conflicting things in this file, specifically that the versions are hard coded into it.
Based on this, how can I run this app on my local server, if the above steps I've done, just doesn't work? I'm using Ubuntu, if that helps.
You're dealing with what is known as dependency issues. The point of Gemfile and Gemfile.lock is to insure that there will be no dependency issues for the application and bundle install will handle that. However it is common for versions to be set in the Gemfile to lock to a specific major release version which might allow for minor version updates. This will look something like:
#Gemfile
gem 'rails', '4.2.10'
gem 'pg', '0.20.0'
gem 'after_party', '~> 1.10' #minor version updates will run here
gem 'kaminari', '~> 1.1'
ruby '2.3.6'
This ia a brief example. Now when you run bundle install it will make sure everything is compatible with these versions. While running bundle update will only update the versions with ~> before the version and will upgrade only minor semantic versions as they are not supposed to have breaking changes.
So, why is your app not working? Well the Gemfile should have contained a ruby version. RVM should determine your ruby version in .ruby-version file in base of your rails app and should match the version in Gemfile. If you need to upgrade your ruby version bundler will help insure all your gems are compatible with that version and with each-other. You'll first need to upgrade your ruby version with RVM, then set it in Gemfile.
However, there is no guarantee that out of date gems will be compatible. That's the whole point of locking them so that you know which versions are stable at a give point in time. Updates / upgrades to gems have to be tested for compatibility which can sometimes be a project.
Also see Rails Bundle, gems conflicts, best way to solve it
You can create a .rvmrc file or .ruby-version and .ruby-gemset files for isolating gems for your projects. Here's the official documentation on that - https://rvm.io/workflow/projects#project-file-ruby-version
you can add
echo '2.3.1' > .ruby-version and echo 'newgemset' > .ruby-gemset into working folder
then run
cd ./
rvm install ruby-2.3.1
gem install bundle
bundle install

behavior of bundler in rails 3.2

when i run bundle install the first time this will create a gemfile.lock for me
after this my question is :
if i run bundle install for the second time what does bundler do ?
i think it look first at gemfile.lock and check each line, and then look in the gemfile and check gems that not exist in gemfile.lock then install them !!! i'm not sure , and i which if someone can explain that to me (step by step )
second question is :
for example i add a gem like this gem 'nokogiri', '~> 1.4.2' , suppose after 1 month, version 1.4.3 is available. i think it will be installed automatically if i run bundle install again ?
can this new version "with tiny update" break things in my app ?
The duty of Gemfile.lock is to lock the versions of the gems you use.
bundle install installs all gems in your Gemfile that are not in your bundle and records the version in Gemfile.lock.
bundle install only installs the versions of your gems, that are recorder in Gemfile.lock. It will never update any gem.
For updating gems, use bundle update. It looks for new versions of your gems, installs them and records the new versions in Gemfile.lock.
If you specify a version in your Gemfile like in your example
gem 'nokogiri', '~> 1.4.2'
bundle upate would only update nokogiri to revisions < 1.5
Any update (in fact any change) might break your application, but minor updates are supposed to be completely backward compatible (stable API, only new tests, all old test pass)
From the documentation,
(...) the first time you run bundle install (and a Gemfile.lock does not exist), bundler will fetch all remote sources, resolve dependencies and install all needed gems.
If a Gemfile.lock does exist, and you have not updated your Gemfile, bundler will fetch all remote sources, but use the dependencies specified in the Gemfile.lock instead of resolving dependencies.

how to include all project gems into the gemfile?

I work as a developer supporting several apps built in Rails, often I need to install gems that are not included into the gem file.
Last day I build a project and when I try to run it on another computer I experienced some issues with missing gems, a lot actually and I didn't know where to get a list of all the missing gems or how to install them.
The question is, is there a way to include all the gems that the project needs into the gem file so next time someone try to run it on another computer it will be enough to use the comand bundle install.
You need to include the Gems in your Gemfile, and then run bundle install on ANY new machine in order to install those Gems and their dependencies. For example:
source 'https://rubygems.org'
gem 'rails', '3.2.6'
gem 'jquery-rails'
gem 'mongoid'
gem 'devise'
gem 'cancan'
With this example, all dependencies of rails such as Active Record, Action Pack and so on will be installed when bundler installs rails. The same for the remaining gems and their dependencies.
If you are planning, and it appears that you are, to spend much time with rails, you should really read up on Bundler.

Resources