I'm creating a gem and have been testing it on MRI, JRuby, and Rubinius. I have a section of code which checks to see if the Linux/Unix cli command 'factor' exists on the platform the gem is installed on. If it exists I wrap some ruby around it and use it. If 'factor' doesn't exists then I create pure ruby versions of the same methods. To do this, I invoke the 'factor' command. If it exists I create the methods I want using it. If it doesn't exists, an error is thrown which I use a 'rescue' section to resolve to create pure ruby versions. Below is code to show the use of 'rescue': If the system is a RUBY_PlATFORM which has 'factor' (Linux/Unix) then the line: `factor 10`.split(' ') !=  will be performed with no error, and the code will proceed in sequence. If the system doesn't have 'factor' a sys error is thrown and 'rescued'. I test this on my Linux system by running it with the correct spelling of 'factor', which outputs 'OS versions'. I then create a false cli command 'factorz' and run the code, and for MRI (2.2.1 and 2.1.2) and Rubinius (2.5.2) a sys error is thrown and the 'rescue' section is invoked correctly and 'Ruby versions' is shown. However, on JRuby 1.7.19, in both cases I get 'OS versions'. So apparently, JRuby isn't throwing a system error when it attempts to run a non-existent cli command, which doesn't conform to MRI (2.2; 2.1). 1)Is this a bug in JRuby, or is this allowed behavior? 2)Is there a 'better' more universally transferable way to do this? begin # Test Operating Systems if *nix cli command 'factor' exists `factor 10`.split(' ') !=  #`factorz 10'.split(' ') !=  # mimic nonexistent on system # code would go here to create 'factor' coded methods puts 'OS versions' rescue # if 'factor' not in system use pure ruby versions # code would go here to create pure ruby coded methods puts 'Ruby versions' end
on 2015-03-21 05:45
on 2015-03-21 06:37
If you don’t want to do the test on Windows, then I believe you can rely on the existence of the 'which' command. In that case: system(‘which factor’) …will return true if it’s available, and false if it’s not. This is from my Mac, which does not have factor: 2.1.2 :003 > system('which ls') /bin/ls => true 2.1.2 :004 > system('which factor') => false Of course, this does not guarantee that the ‘factor’ executable found is the one you want. You could do something like this: def factor_available? RUBY_PLATFORM != ‘mswin’ && system(‘which factor’) end You might need to tweak the platform test; there are other values of RUBY_PLATFORM that are Windows, but some of them (e.g. ‘cygwin’, and maybe ‘mingw’?) simulate Unix so may not need to be excluded. - Keith
on 2015-03-21 17:13
Hey Keith, thanks. Doing something like this: if system('which factor'); puts 'Yes factor' else 'No factor' end is much cleaner and transportable. I tested it on my system with MIR (1.8.7, 2.1.2, 2.2.1), JRuby-1.7.19 and Rubinius-2.5.2, and there were no problems. I'll try it later on my Win7 system with Rubyinstaller rubies. FYI, I started out using the RUBY_PLATFORM value to check against, but soon realized I would have to know if 'factor' runs on all the possible ruby platforms to make if universally transportable, so I started checking directly for 'factor' being on a platform. In Unix 'factor' has been standard since 1974, and in Linux and BSD since their inception, so I'm not too concerned about possible false positives on other platforms. https://en.wikipedia.org/wiki/Factor_(Unix) The still open question, though, is JRuby's non-conformist to MRI behavior handling rescue in the original example. This can obviously have catastrophic consequences for people expecting their MRI code to operate the same on JRuby.
on 2015-03-21 19:03
open4 (gem on mri, native on jruby) will raise an error if it doesn't find the executable. try something like this: if IO.respond_to?(:popen4) #jruby def open4(*args) IO.popen4(*args) end else # mri require 'open4' end begin open4("monkey") rescue print "monkey not available" end