Understanding the Gemfile.Lock File

What is the difference between Gemfile and Gemfile.lock in Ruby on 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.

Understanding Gemfile.lock: Is it okay to delete Gemfile.lock then run bundle install again?

You're probably not going to ruin your dev environment. However, you might end up with newer versions of gems than you had before. It depends on how you have defined them in Gemfile.

If you're using entries like:

gem "rails"

Then you'll get the latest rails gem, whatever that might be.

If you're using entries like:

gem "rails", "3.2.11"

Then you'll get 3.2.11 again.

Having said all of that, this is what branches are for. Make a branch in git, hg, or whatever you're using, blow away Gemfile.lock, run bundle install, and then check your test suite. If it's horrible, then you can abandon the branch while you figure out what went wrong.

Another tip: Any time I've ever wanted to do this, I found that it was useful to clear out all of my installed gems as well. If you're using rvm with gemsets this is as simple as running

rvm gemset empty [gemset_name]

Parsing direct and indirect Gems of Gemfile.lock file

indirect dependencies were automatically ignored

It would have helped if you'd included the full output. I just ran it myself, and you get:

[{"name"=>"coderay", "version"=>"1.1.3"},
{"name"=>"domain_name", "version"=>"0.5.20190701"},
{"name"=>"http-accept", "version"=>"1.7.0"},
{"name"=>"http-cookie", "version"=>"1.0.4"},
{"name"=>"json", "version"=>"2.5.1"},
{"name"=>"method_source", "version"=>"1.0.0"},
{"name"=>"mime-types", "version"=>"3.3.1"},
{"name"=>"mime-types-data", "version"=>"3.2021.0704"},
{"name"=>"netrc", "version"=>"0.11.0"},
{"name"=>"rest-client", "version"=>"2.1.0"},
{"name"=>"unf", "version"=>"0.1.4"}, # <------ !!!!!!!!!!!!
{"name"=>"unf_ext", "version"=>"0.0.7.7"},
{"name"=>"yaml", "version"=>"0.1.1"}]

So in summary, the indirect dependency of domain_name, i.e. unf, which is presumably what you were referring to, is included further down the list. Your code already works exactly as you intended.

One minor point, though: You can simplify the implementation a little by doing this:

gemlock_array = context.specs.map { |s| {'name' => s.name, 'version' => s.version.to_s} }

In ruby, assigning a temporary array and appending to it within a .each loop is usually sub-optimal. Use map instead, to just construct the array directly.

is it desirable to remove Gemfile.lock?

Does bundle install take specific gems in my Gemfile or Gemfile.lock?

bundle install looks first into gemfile.lock, then looks into gemfile to generate a valid gem list, checks, tries to resolve the dependencies, and then install/update the gems.

My Gemfile and Gemfile.lock are not the same.

They don't need to be the same. gemfile.lock is a specific file to keep the gems' state at the time of running bundle install/update.

Do I have to remove Gemfile.lock?

You can, but then bundle install will generate gemfile.lock again. Then, you could really lose and break all gem dependencies, and might need to resolve them manually.

As an investigation procedure, you can copy old gemfile.lock to a secluded place, then regenerate gemfile.lock, and compare both with diff

Gemfile with exact versions vs Gemfile.lock

No, an exactly specified Gemfile and using a Gemfile.lock is not the same.

Your Gemfile might include all gems you are using with a specific version. But the Gemfile.lock will also include all gems that are dependencies of the gem you use. That means that a typical Gemfile.lock will include way more gems when a Gemfile.

Furthermore: You might have gems or gem versions to your Gemfile that are incompatible with each other. A Gemfile.lock is generated by bundler and represents a set of gem versions that are compatible with each other. If bundler is not able to fulfill all required dependencies then it will not generate a Gemfile.lock.

That said: Pin only versions in your Gemfile that you need to pin because of version requirements of your app. Let bundler find a valid combination and check that Gemfile.lock into version control system.

Understanding the tilde operator in Gemfile.lock

short answer: as pointed by Holger in the comments, ~> 0.6, >= 0.6.4 means >= 0.6.4 and < 1.0.

The ~> operator is called pessimistic operator (or twiddle-wakka), and its objective is to guard the gems from potential bugs/failures in future releases.

When you're building a gem, you must create a special Specification Class and put it in a .gemspec file or in a Rakefile. This class contains the information for the gem, like its name, version, license and the dependencies.

And is a good practice specify the dependencies following a pessimistic version constraint. Therefore, notations like ~> 0.6, >= 0.6.4 are very common.

You can find more information here.



Related Topics



Leave a reply



Submit