Understanding the tilde operator in Gemfile.lock - ruby

I currently have a dependency of the following
i18n (~> 0.6, >= 0.6.4)
I've been having a read through of the Ruby Gems - Declaring Dependency Guide
And I've found out that the '~> 0.6' part means anything between 0.6 and 1.0 - correct me if that's wrong.
But I'm still confused, what does this actually mean with a second comma separated value?
A colleague believes it means
>= 0.6.4, <= 0.7
But I'm not so sure.

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

How to set up a .ruby-version less strict?

I like to setup the version of Ruby I am using on each project by setting up a .ruby-version file, but I find it very strict, especially if I am sharing my code.
If I declare this for example:
#.ruby-version
3.0.2
The code is going to request this ruby version and it won't accept any other no even: 3.0.4 which I know it will also work. This makes my code less sharable.
Is there any way I can use version description syntax like in the Gemfile file?
>= 3.0.0
>= 3.0.2, < 3.3
~> 3.0
It's funny that you even said "like in the Gemfile...", because you can define the required ruby version in the Gemfile, instead of having a .ruby-version file:
ruby '~> 3.0' # or whatever
gem 'some-dependency'
gem 'another-dependency'
# ...

ruby gem dependency issue, need to know if a gem is compatible before running bundle install?

I'm setting up the GemFile following some tutorial.
If an older version of a gem specifies its dependency as rake ~>10.3 on rubygems.org
does that mean a later version of rake won't work with this gem?
rake ~>10.3 means: 10.3.0 <= version < 11.0.0. The dependency constraint is not saying that rake must be exactly version 10.3.0.
The only thing I can say with certainty is that the bundle will refuse to install unless it contains a version of rake in that range.
Would the gem actually work with a later version of rake? Maybe. It depends what the code actually does! The old version of this gem was probably (?) written before rake v11.0.0 was released, therefore there was no way of knowing, at the time, whether or not it would be compatible.
You could create your own copy of the old gem version and try loosening/removing the dependency constraint, but I wouldn't recommend it; it's best to just upgrade all code to use newer (ideally the latest) versions, or downgrade other libraries for compatibility if absolutely necessary.
Gem dependency is a case-by-case basis. There is no possible way to say that any gem will or won't be backwards compatible, you have to test. The "closer" the version is, the more likely it is to be compatible, but this is in no way a rule that you can go by or trust.
In addition, I don't know if you are understanding the syntax of that either. ~> 10.3 does not mean that rake must be version 10.3. It is a slightly confusing operand, but limits the version to a subset of versions.

Lock gem dependency versions for different rubies

Rubygems doesn't provide a proper way to specify different dependencies for different ruby versions. If we put a conditional in the gemspec, it can switch what gets installed:
if RUBY_VERSION < "1.9"
# ruby 1.8 only supports nokogiri < 1.6
s.runtime_dependency "nokogiri", ">= 1.4.0", "< 1.6"
else
s.runtime_dependency "nokogiri", ">= 1.4.0"
end
But, this doesn't control what gets loaded. If there's a newer version in the load path, that would get loaded even if it's incompatible with ruby 1.8.
I'm not sure if this is actually a problem: If you're using rbenv/rvm etc. then you have different gem paths for each ruby, so hopefully you'd never have both installed in the same place. I think even the standard gem paths are divided by compatibility versions (1.8 / 1.9.1). Is that intended to take care of this, or could you ever get into a situation where both versions are installed together?
The other approach would be to leave the gemspec open-ended (without the conditional), and warn users to set the correct version constraint in their Gemfile if they need it.
Which way is preferable?
I believe this is just the nature of how bundler and requiring gems works. It's one of the great benefits to tools such as rvm.

How to do an "OR" when requiring a Gem version

Currently I have a Gemspec that requires a specific version of Rails 3.x with Rails > 3.1:
Gem::Specification.new do |s|
# (...)
s.add_dependency "railties", "~> 3.1"
# (...)
end
I am looking to update this statement to require ~> 3.1 OR ~> 4.0.0. I had tried already:
~> 3.1, ~> 4.0.0
~> 3.1 OR ~> 4.0.0
~> 3.1 || ~> 4.0.0
~> 3.1 ~> 4.0.0
None have worked. Is that possible with the current RubyGems version?
For now I am using > 3.1, but the real question is if that's possible.
Since you are using ~>, it seems as if you are willing to use any version of the gem that is after 3.1, that is, any 3.x OR any 4.0.x, but not a 4.x where x is greater than 1.
If that is your intention, then according to the rubygems guide, you'll want to use a pattern like:
spec.add_dependency 'library', ['>= 3.1', '< 4.1']
I think it might be the addition of brackets that you need.

What does tilde-greater-than (~>) mean in Ruby gem dependencies? [duplicate]

This question already has answers here:
Meaning of tilde-greater-than (~>) in version requirement?
(4 answers)
Closed 8 years ago.
What does ~> mean in the context of Ruby gem depenedencies?
For example, when opening a legacy project in the RubyMine IDE, I get this
message
Gems required for project are not attached:
arel (~> 2.0.2),
rspec-expectation (~> 2.5.0)...
I've seen this tilde-greater-than notation elsewhere in the Ruby world (it's not
specific to RubyMine). Does this operator have a name other than the
awkward-sounding tilde-greater-than?
It means "equal to or greater than in the last digit", so e.g. ~> 2.3 means
"equal to 2.3 or greater than 2.3, but less than 3.0", while ~> 2.3.0 would
mean "equal to 2.3.0 or greater than 2.3.0, but less than 2.4.0".
You can pronounce it as "approximately greater than".
§ Pessimistic version constraint
it means bring any lower version equal or greater than, but not a major version.
So for example arel (~> 2.0.2), will use (if availble) versions
2.0.2
2.0.3
2.0.? (as long as ? is >= 2)
but it won't use 2.1.?
According to the internet
If a RubyGem dependency uses the syntax "~> 1.4.37", that means "a version greater than or equal to 1.4.37, but not 1.5 or higher." 1
In other words, for you
arel can be 2.1 > version >= 2.0.2 and
rspec-expectation can be 2.6 > version >= 2.5.0.
What this means is that you are expecting a gem that is version 2.0.2 or higher, but not 2.1 in the case of arel (~> 2.0.2) This is done since people are not supposed to release breaking syntax changes in minor revisions. So arel 2.0.3 would be expected to have bug/stability fixes over 2.0.2

Resources