Gem Dependencies Versions Meaning

Gem dependencies versions meaning

The ~> operator means: match within the same version, depending on how specific you want it to be, here's some examples:

 Specification From  ... To (exclusive)
">= 3.0" 3.0 ... ∞
"~> 3.0" 3.0 ... 4.0
"~> 3.0.0" 3.0.0 ... 3.1
"~> 3.5" 3.5 ... 4.0
"~> 3.5.0" 3.5.0 ... 3.6

Source

What does ~ mean in ruby gems dependencies?

It basically means greater than. or equal to, the last digit of the version.

i.e. "~> 1.0" is equivalent to ">= 1.0 and < 2.0". Thus 1.1, 1.5.2, 1.9.9 will all match.

Another example: "~> 1.1.0" would mean ">= 1.1 and < 1.2"

Refer also to: What does tilde-greater-than (~>) mean in Ruby gem dependencies?

What does tilde-greater-than (~) mean in Ruby gem dependencies?

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

Manage gem dependencies based on Ruby version

Logic like you show will work fine for development dependencies since it will be evaluated at bundle install time.

It will not work for runtime dependencies since the logic will be evaluated at gem-build time and not when the gem runs in another environment.
RubyGems does not provide a way for you to specify different gems based on the runtime environment, so the only way you could support that would be to release two differently named versions of your gem with different gemspecs.

Personally, I don't see the point of putting development dependencies in the .gemspec, so I always just add these to my Gemfile and reserve the gemspec for runtime dependencies only.
This separates the concerns better and makes it clear that gem selection logic can be used in the Gemfile, but not in the gemspec.

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.

Meaning of tilde-greater-than (~) in version requirement?

The RubyGems manual calls this a
pessimistic version constraint.

Assume you have specified an n-part version number, e.g. 1.3 (2-part) or
3.5.6.2 (4-part) as the constraint. Then, in order to fulfill the constraint,
a version number must satisfy both of the following conditions

  1. The first n-1 parts of the version number must be identical to the first n-1
    parts of the constraint
    (e.g. 1.x or 3.5.6.x match, but 0.x or 3.5.7.x don't) and

  2. The last part of the version number must be greater than or equal to the last
    part of the constraint
    (e.g. 1.9999 and 3.5.6.2 match, but 1.2 or 3.5.6.1 don't).

In other words


~> x1.x2.x3. … .xn-2.xn-1.xn

matches


x1.x2.x3. … .xn-2.xn-1.y, y >= xn

The reason this is called a "pessimistic" constraint, and also the use case for
it, is that when you just say > x.y.z, you are being optimistic: you assume
that from here on out, until all eternity, the API will never ever change. This
is of course a pretty bold assumption. However, most projects have rules about
when they are allowed to
break backwards compatibility,
and how they have to change their version number when they do break backwards
compatibility. You can encode those version numbering rules using a pessimistic
constraint, and thus you can be sure that your code will always continue to work
(assuming that the author of the other project actually adheres to his own
rules, which unfortunately isn't always the case).

What is the difference between ~ and = when specifying rubygem in Gemfile?

That's a pessimistic version constraint. RubyGems will increment the last digit in the version provided and use that until it reaches a maximum version. So ~>0.8.5 is semantically equivalent to:

gem "cucumber", ">=0.8.5", "<0.9.0"

The easy way to think about it is that you're okay with the last digit incrementing to some arbitrary value, but the ones preceding it in the string cannot be greater than what you provided. Thus for ~>0.8.5, any value is acceptable for the third digit (the 5) provided that it is greater than or equal to 5, but the leading 0.8 must be "0.8".

You might do this, for example, if you think that the 0.9 version is going to implement some breaking changes, but you know the entire 0.8.x release series is just bugfixes.

However, simply using ">=0.8.5" would indicate that any version later than (or equal to) 0.8.5 is acceptable. There is no upper bound.



Related Topics



Leave a reply



Submit