Pessimistic Prerelease Peculiarities
The assumption
There seems to be an assumption that the pessimistic requirement operator (aka ~>
, aka the twiddle-wakka) is short hand for a pairing of >=
and <
.
e.g: in a Gemfile
we see ~> 1.1
as equivalent to: '>= 1.1' '< 2.0'
.
That seems reasonable, but be warned, it breaks down when prerelease gems are involved.
The code
Firstly, here's a method to check a gem's version against some requirements:
1
2
3
def check(version, *requirements)
requirements.map { |v| Gem::Requirement.new(v).satisfied_by? Gem::Version.new(version) }.all?
end
We can use this to check if ~> 1.2
does behave indeed the same as '>= 1.1' '< 2.0'
. Let's check both a good version (which meets the requirements) and a bad version (which does not):
So far, so good.
The peculiarity with prerelease
However, this equivalence doesn't hold when the version being checked is a prerelease:
We can see that the pessimistic operator doesn't think this prerelease gem meets the requirement, but our supposedly 'equivalent' version does. What gives?
It happens because a less than 2.0 requirement is true if the version is a prerelease of 2.0:
However a pessimistic 1.1 requirement is false if the version is a prerelease of 2.0:
Making sense of it
Rephrasing those two versions as questions, it's clear that both these answers make sense:
- Should a prerelease of N be considered a lower version N? Yes.
- Should a prerelease of N+1 be pessimistically compatible with version N? No.
It is in fact our initial assumption that ~> 1.1
is equivalent to: '>= 1.1', '< 2.0'
that is incorrect.
So it seems in the absence of anyway to express "less than version 2.0 and any prerelease thereof" that the pessimistic operator is more than just a convenient short hand, it's the only correct way to specify a requirement pessimistically.
Need help with your project?
We specialize in Ruby on Rails and JavaScript projects. Code audits, maintenance and feature development on existing apps, or new application development. We've got you covered.