How to check for API compatibility between Ruby versions? - ruby

Our team maintains a ruby script that must support any ruby >= 1.9.3 (yes, that's a pretty old ruby version but this is something outside our control at the moment). Recently, we added a change that included the verification of a regexp using match? and everything was going well until one of the users reported that the script was exploding for ruby 2.3 with the message:
undefined method `match?' for #<Regexp:0x000000018471e0> (NoMethodError)
Turns out this happens because the match? method is available in ruby >= 2.4.
We have been running ruby -c script.rb with multiple versions of ruby (1.9.3, 2.0.0, 2.1.10, 2.3.7, 2.5.1, 2.6.3, 2.7.4) as part of our test suite and this didn't show up as a syntax error and I suspect it's because the actual syntax is "correct" but the method is simply not available in some versions of ruby. We also tried rubocop, hoping that it could detect these incompatibility issues but it doesn't report any error either.
So, my question is, what's the best way to check for this API compatibility issues between multiple ruby versions?

Running ruby -c with the oldest Ruby you support is a good start, as it will detect if you are trying to use a newer syntax.
For using methods that are new:
Run your tests suite in both the oldest and newest Ruby versions you want to support.
Consider using my backports gem to make it possible to use newer API even on old Rubies. For example, it includes Regexp.match? among the hundreds of backports...

Do you have an automated test suite? If so, you can set up your CI to test against multiple Ruby versions, e.g.:
https://github.com/actions/setup-ruby#usage
(Edit: I see you did mention a test suite, so it sounds like you have a gap in the test coverage, or you're not running the tests against each Ruby version?).

Related

Do old gems always work on later versions of ruby?

I am using a quite recent version of ruby (2.5.1) but some old gems. I am having some issues. I was wondering, is it correct that some gems work only with certain versions of ruby?
If a gem worked with ruby 2.3.0, is it true that it will definitely work with 2.5.1 (i.e. because 2.5.1 > 2.3.0)? Or is that not always the case?
I guess what I'm asking is are newer ruby versions always backwards compatible with older gems?
If a gem worked with ruby 2.3.0, is it true that it will definitely
work with 2.5.1
This is not correct. Programming languages are evolving while growing. This means language maintainers are doing lots of improvements or refactorings that they are new features or removing old components from the language. When the language community announces for new features or removing old feature such as Fixnum in ruby, the developers should follow the instructions and refactor their codebase accordingly. In other words, developers should have a good test coverage to detect any fail and fix it instantly.
In your scenario, as well as I understand you do not have a test coverage. The only but the simple thing should do is just upgrade your gems' versions to latest.
Gem is simply a plug-in library written in Ruby.
Of course, Ruby is developing, new features are appearing, old ones are disappearing.
It's best practice to specify Ruby version in .gemspec file. For example, like this one.
But if not, then you have to manually check the performance. So you can read gem source code or try to use your gem and check it.
For automation, of course, it is best to use tests.
Starting at Ruby 2.1.0 the version policy has been that a change in the MINOR version may introduce API breaking changes.
Should any gem happen to use an API that changes, an incompatibility will arise.
The MINOR version number has changed twice between 2.3.* and 2.5.* so even if a gem happens to have been written in accordance with the documented API, there's no guarantee that it will continue to work unless the gem's maintainer takes the effort to test the gem (and upgrade it if necessary). Automated test suites help a lot.
A standard way to document version compatiblity that is actually tested against is by providing required_ruby_version in .gemspec files.
Interestingly, if a particular gem is really badly written, I imagine it might break even between compatible versions of Ruby. That's not something I've encountered in the Ruby ecosystem but I've made a similar mistake writing Java code (and Java is famous for its backward compatibility) where my own code accidentally used a class that wasn't part of the API. There are many gems. Who knows what's out there? :)

Running Newer Ruby Version Next to Existing Ruby Version

DISCLOSURE: I know very little about Ruby beyond some basic code syntax. Bear with my idiocy.
Ruby 1.8's OpenSSL library doesn't seem to support TLS 1.2. However, there are apps running that are dependent on 1.8, so I want to see if I can run a newer version of Ruby concurrently on the same system and get it set up with newer versions of the same gems.
Currently version 1.8 is at /usr/lib/ruby/1.8. Ideally, I'd like to keep the same structure and install a newer version (not sure what the most recent, stable version is - whether it's 2.3.x or 2.4.x).
That said, I am not a Ruby admin. I inherited a server from someone else who decided Ruby was the best way to do things, despite there being no other Ruby experience within the company, and then they left. I know some system admin stuff, but I don't know:
How backwards-compatible Ruby versions are (e.g. would an app built against 1.8 run without any major modifications on 2.4.1).
How gems work / get updated. Can 2.4.1 use gems from 1.8, or are gems tied to specific Ruby versions? Can there be a mix-and-match? Is there a migration path of some kind?
How to properly manage two different concurrent versions (how to tell an app to use one version over the other, or prevent existing apps from automatically trying to use the new version and breaking if they're not compatible).
Any best install practices (I usually compile from source, but am open to suggestions).
Is it even possible to just update Ruby's OpenSSL library without updating the whole Ruby app? It's currently on OpenSSL 0.9.8o, so it's pretty significantly behind the times.
The server is running Debian 6.0.6 (I'm more familiar with Red Hat and CentOS, though, so any hints on package management, etc... related to this issue would be welcomed).
Modern ruby has "matured" and become very stable. Upgrading from 2.0.0 --> (the latest stable) 2.4.1 is generally quite easy. However, ruby went through a period of fairly major (necessary!) changes from 1.8 --> 1.9 --> 2.0; this part of the upgrade may be problematic.
Gems are installed within the current ruby installation. So for example, you currently have the "ruby 1.8 version" of CanCan. If you update the ruby version of this application, you will need to re-install all gems (presumably via bundle install) for the ruby version. The migration path is basically: Get as comprehensive a test suite as possible; upgrade gems as much as possible within that ruby version; update the ruby version; fix tests and/or code if necessary; repeat.
Use a tool like rvm or rbenv to install multiple concurrent ruby versions on one machine.
See point 3. You probably don't need to compile anything from source.
Ruby 1.8 is old. Support for it was dropped back in 2013. Your application will undoubtedly have a huge list of outdated libraries now, with all sorts of security vulnerabilities -- that's what happens when you don't update it for 6+ years! From a security standpoint, I would not suggest trying to find some workaround for this one OpenSSL issue and ignore the larger problem here.

How do I determine my gem's required ruby version?

I am creating a gem and I have the suspicion that it may not work on certain Ruby versions. Is there a way to quickly check which Ruby versions it is compatible with? My current method is using RVM and switching to different Ruby versions to test, but that may be an inefficient way to do it. I was also wondering if I could narrow it down to a specific patch version.
#Matt Schuchard suggested the right way to do this (in the comment)
For example, you can check how to do this with GitHub Actions. You can test it not only for specific ruby version but also on different OSes
https://github.com/metanorma/metanorma/blob/master/.github/workflows/rake.yml

Ruby : What changes needed to make test-unit-1.2.3 working with Ruby-2.4.1

I am new to Ruby Development. Now i am working on ruby test-framework code which was working fine with Ruby-1.8.7
Now i want to upgrade ruby for this framework. I have found that test-unit-1.2.3 is included in Ruby-1.8.7 so i have installed it separately with Ruby-2.4.1.
Currently i am facing method missing issue ["register_autorunner"] with this combination. Because these method have not been used in ruby-1.8.7
Can anyone please tell me other changes needed to make this combination [Ruby-2.4.1 , test-unit-1.2.3] working.
Thanks in advance
You should update to TestUnit 3.x, which will have a higher chance of working with Ruby 2.x. Then you need to figure out the changes between Ruby 1.8.7 and Ruby 2.4.1, and how to fix your existing code, which is most likely broken, even after you have fixed/updated your unit test configuration.
Also, consider a switch to Minitest or Rspec, as they are a lot more popular today, so it will be easier to find examples and supporting tools for them. Minitest is also the default test framework used by Ruby on Rails currently.
References:
https://www.jetbrains.com/research/devecosystem-2017/ruby/
http://guides.rubyonrails.org/v5.1/testing.html

How to figure out the exact ruby version that jRuby is compatible with

When updating jRuby, I'm always having a look at their release notes to figure out which ruby syntax I'm able to use. Quite recently, the change logs just say Ruby 2.x compatibility. Is there a way or place to find out against which exact ruby version it is compatible? I.e. ruby 2.2 differs from 2.3 quite a lot. Why are they just writing 2.x?
When you do a
jruby --version
two version identifiers are printed. The first one gives the jRuby version, and the second one gives the Ruby language version which this jRuby is based on.

Resources