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
Ruby Convert Array to Nested Hash
How to Pass Multiple Arguments to a Ruby Method as an Array
What Does 'If _File_ == $0' Mean in Ruby
Difference Between Truncation, Transaction and Deletion Database Strategies
Bundle Failing - Can't Find the Postgresql Client Library (Libpq)
How to Extract a Sub-Hash from a Hash
How to Get Haml to Work with Rails
In Ruby's Test::Unit::Testcase, How to Override the Initialize Method
How to Pass a Parameter for Gem Installation When I Run Bundle Install
How to Get Readline Support in Irb Using Rvm on Ubuntu 11.10
Ruby on Rails: Alias_Method_Chain, What Exactly Does It Do
Rails Activesupport Time Parsing
Checking If a Variable Is an Integer
Return First Match of Ruby Regex
Why Does My Ruby 'Ri' Tool Not Return Results in Command Prompt
Nokogiri Was Built Against Libxml Version 2.7.7, But Has Dynamically Loaded 2.7.3