behavior of bundler in rails 3.2 - ruby-on-rails

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.

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

Why does bundler update gems when it knows the gemfile requires a specific version

This seems to happen a lot. I run bundle update or bundle install and for one reason or another I often get something like this:
You have already activated kgio 2.8.0, but your Gemfile requires kgio
2.7.4. Using bundle exec may solve this
I then have to go and run: sudo gem uninstall kgio and select kgio 2.8.0 to uninstall it.
Why does bundler even update the gem if it knows my gemfile locks those gems to a specific version. I NEVER install gems outside of the gemfile and bundler so Im not circumventing its conventions. I do have another project on my machine, but I havent ran a bunle update on that project in a long time -- is there some mix up there? Has this happened to anyone else? Am I doing something wrong?
actually bundle update the gems specified (all gems, if none are specified), ignoring the previously installed gems specified in the Gemfile.lock.
whereas bundle install will fetch all remote sources, but use the dependencies specified in the Gemfile.lock instead of resolving dependencies.
and use
gem cleanup
This command will remove (uninstall) all the versions of a gem, except for the latest one.
bundle update, installs newer versions of your gems and states that in your Gemfile.lock. bundle install just makes sure you have the correct versions installed. I suppose you are running bundle install in projects with different locked versions for kgio.

Updating Gemfile from Gemfile.lock, to freeze gems

After generating a Gemfile.lock from Gemfile, is there any tool to round-trip back to freeze versions in the Gemfile. I'd rather avoid doing it manually.
Background: It's good practice to freeze minor version on gems, e.g. if Gemfile.lock is 2.4.1, I'd want to update Gemfile to include ~> 2.4 (as explained here).
You should define the gem verions that you wanna freeze your app to in the GemFile itself before you run bundle install.
Once, you have that define and you run bundle install, it will generate a Gemfile.lock with the versions of all installed gems and their dependancies.
again, .lock file is auto-generated ans should not be manually editted. this is what the GemFile is for.

What is the difference between Gemfile and Gemfile.lock in Ruby on Rails

I am a beginner to Ruby on Rails and I am using Rails 3.0.9.
What is the difference between Gemfile and Gemfile.lock in Rails?
The Gemfile is where you specify which gems you want to use, and lets you specify which versions.
The Gemfile.lock file is where Bundler records the exact versions that were installed. This way, when the same library/project is loaded on another machine, running bundle install will look at the Gemfile.lock and install the exact same versions, rather than just using the Gemfile and installing the most recent versions. (Running different versions on different machines could lead to broken tests, etc.) You shouldn't ever have to directly edit the lock file.
Check out Bundler's Purpose and Rationale, specifically the Checking Your Code into Version Control section.
Usually we write dependencies in Gemfile as:
gem "nokogiri", "~> 1.4.4"
gem 'bcrypt-ruby', '~> 3.0.0'
gem 'uglifier', '>= 1.2.3'
..
Here you basically say: "I want nokogiri as long as it’s greater than version 1.4.4", etc. Now suppose that I have set up my Gemfile 8 months ago and I successful setup my app with this requirement. 8 months ago nokogiri version was 1.4.4. My rails apps was running perfectly without any problems with this version.
Now think I'm trying to build with the same Gemfile. But if we look at nokogiri versions we see that the current stable version has changed to 1.4.9. That means if we try to build, bundler will install version 1.4.9 of nokogiri (suppose we don't have Gemfile.lock).
What does it mean ?
As you see if you don't have any Gemfile.lock and run:
bundle install
then the currently used gems can be different at any time. Your app used the version 1.4.4 and it works 8 months ago without any problems, but if you try to build it now you get the version 1.4.9. Maybe it's broken with the latest version of nokogiri, the awesome feature you used with 1.4.4 is not more available, etc..
To prevent this kind of problem Gemfile.lock is used. In Gemfile.lock only the exact versions are written and thus only these will be installed. That means if you distribute your app with a Gemfile.lock, every machine will have the same gems installed and most important they all get the same version. This will give you a stable and common deployment stack.
How is Gemfile.lock created?
It is automatically created with the first:
bundle install
command. After that everytime you run bundle install, bundle will first look up Gemfile.lock and install the gems specified there. It's an habit to distribute this file among your projects to provide consistently and stability.
How to update Gemfile.lock?
If you're happy with the the latest version of your apps than you can update Gemfile.lock. Just reflect your changes to Gemfile. That means change the dependencies to the new exact versions in Gemfile. After that run:
bundle install
This will update you Gemfile.lock with your newest version of apps.
The Gemfile.lock
When you run bundle install, Bundler will persist the full names and versions of all gems that you used (including dependencies of the gems specified in the Gemfile(5)) into a file called Gemfile.lock.
Bundler uses this file in all subsequent calls to bundle install, which guarantees that you always use the same exact code, even as your application moves across machines.
Because of the way dependency resolution works, even a seemingly small change (for instance, an update to a point-release of a dependency of a gem in your Gemfile(5)) can result in radically different gems being needed to satisfy all dependencies.
As a result, you SHOULD check your Gemfile.lock into version control. If you do not, every machine that checks out your repository (including your production server) will resolve all dependencies again, which will result in different versions of third-party code being used if any of the gems in the Gemfile(5) or any of their dependencies have been updated.

Resources