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

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'
# ...

Related

Which version of gem is used when there is no Gemfile

There is similar question here.
Ruby: Rails: Which version of a gem is used?
But it's about when Gemfile is used.
I want to know if there is no Gemfile, which version of gem is used.
For example I have 4 versions of selenium-webdriver in my system.
% gem list | grep selenium
selenium-webdriver (2.53.0, 2.48.1, 2.46.2, 2.45.0)
And I just use it by pry and require 'selenium-webdriver. How can I know which version is used? Only the latest is selected?
You probably have more than one gem because each project with Gemfile in your machine have one different version of it.
When using the gem via require or command line without specifying the version the last one - the greater version - will be automatically used.
By convention, in the most part of the cases, you can print the version doing the following:
require 'some_gem'
puts SomeGem::VERSION
# => "3.0.3"

IMDB gem not working on Windows with Ruby 2.2 - Can't use Nokogiri 1.6.7.rc4

I am trying to use the IMDB gem on Windows with Ruby 2.2 but this gem seems to force using an older version of Nokogiri which is not compatible with my Ruby's version on Windows.
This is the message I am getting:
The bundle currently has Nokogiri locked at 1.6.2.1.
I do have installed the RC4 version.
Is there any way to force IMDB to use the RC4 version?
Or other solution I did not think about?
Probably the easiest solution on Windows is to create a Virtual Machine with Linux and then install Ruby.
Windows has many problems with properly handling gems.
Preamble and warning
This solution is only an ugly hack and I don't recommend to use it.
The best solution would be a corrected version of imdb-gem with a (possible) “optimistic” version constraint.
Disclaimer 2: I don't use bundler, maybe this solution does not work exactly as I show it. But the process should be similar for bundler.
Source of the problem
The gemspec of the imdb-gem contains the command:
s.add_dependency 'nokogiri', '= 1.6.5'
or in version 0.8.2
s.add_dependency 'nokogiri', '= 1.6.2.1'
If this would contain an optimistic version constraint like
s.add_dependency 'nokogiri', '=~ 1.6'
you could use the version you use (assumed there is no reason for this specific version).
Hacking the gemspec
During gem install the gemspec is copied to a location like
[ruby-installation-path]/lib\ruby\gems\2.1.0\specifications.
Look for the file imdb-0.8.2.gemspec and make this change:
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
# Begin of Hack the nokogiri version
# s.add_runtime_dependency(%q<nokogiri>, ["= 1.6.2.1"])
s.add_runtime_dependency(%q<nokogiri>, ["~> 1.6"])
# End of Hack the nokogiri version
s.add_development_dependency(%q<rake>, ["~> 10.0.3"])
Then try if your script works.
I tested with nokogiri version 1.6.6.2 and detected no problem.
If the version 1.6.7.rc4 works also I would recommend to ask for a change on https://github.com/ariejan/imdb and a new version of the imdb-gem.

Ruby - Digest::Digest is deprecated; Use Digest

I've been getting this warning whenever I run my tests or start rails server.
When I run grep from .rvm folder I see the following:
grep -R 'Digest::Digest' .
./rubies/ruby-2.1.0/lib/ruby/2.1.0/openssl/digest.rb: warn('Digest::Digest is deprecated; Use Digest')
- additional references to openssl and ruby 2.1.0
So it looks like it's a Ruby 2.1.0 bug. Are there any fixes? There are no patches available yet as far as I can tell.
Whilst my app uses Fog and a bunch of other gems that have issues relating to this message, I'm using patched versions that don't have the bug. So I reckon Ruby is at fault here.
Borrowing the reply from this thread
OpenSSL::Digest::Digest has been discouraged to use from very ancient era such as Ruby 1.8 and finally was deprecated recently.
If you search for the error message, you will see that a lot of gems, including fog, were still using the deprecated syntax.
I assume it will take a while before all the gems will be updated. If you came across the deprecation in one of the libs you use, I encourage you to report it to the maintainer.
Here's a few examples
https://github.com/fog/fog/pull/2473
https://github.com/alexreisner/geocoder/pull/580
https://github.com/ruby/ruby/pull/446
It's likely your Rails app depends on a gem that is using that old syntax.
If you're using bundler, a good way to find out what is causing the problem is to grep through all the gems defined in your Gemfile:
# grep (ack or ag) the problem code
bundle show --paths | xargs grep -r Digest::Digest
# here was my output
~/.gem/ruby/2.1.0/gems/fog-1.15.0/lib/fog/cloudstack.rb: ##digest = OpenSSL::Digest::Digest.new('sha1')
~/.gem/ruby/2.1.0/gems/fog-1.15.0/lib/fog/core/hmac.rb: #digest = OpenSSL::Digest::Digest.new('sha1')
~/.gem/ruby/2.1.0/gems/fog-1.15.0/lib/fog/core/hmac.rb: #digest = OpenSSL::Digest::Digest.new('sha256')
# update appropriate gems (in my case fog)
gem install fog
bundle update fog
Also make sure you aren't locked on a gem version in your Gemfile.
# change
gem 'fog', '~> 1.15.0'
# to
gem 'fog', '~> 1.0'
# or omit the version if you are a cowboy/girl
Use OpenSSL::Digest instead of deprecated OpenSSL::Digest::Digest

Does the Bundler 1.2.0 ruby version check obviate the need for a basic .rvmrc file?

Bundler 1.2.0.pre includes a new "ruby" DSL option. According to Heroku's documentation, they use this new Gemfile syntax to control which ruby version is used when you push your app.
Being pre-release, documentation for the new Bundler option is fairly thin on the ground at the moment, and the Bundler 1.2 roadmap simply lists it as "ruby version check".
My question is: currently I use a one-line .rvmrc file in most of my projects, in which I only specify the ruby version for that project (eg. rvm ruby-1.9.3). I don't use RVM gemsets or anything else (I prefer to vendor all of the required gems within the project, and let Bundler manage the dependencies).
Given my trivial RVM config, will the new "ruby" option in Bundler's DSL mean I no longer need to specify a .rvmrc file at all? Or are they two different things?
(I do like the fact that RVM automatically switches the ruby version when I cd into my project...not sure if Bundler would do that, or if it just warns when the current version doesn't match?)
the new ruby is a function and it will allow anything that finally evaluates to a string.
Unfortunately o read it you would need to use a bundler command which assumes you already have a ruby.
Instead RVM gives you two ways to defining ruby in Gemfile:
1) ruby "1.9.3" - simple strings
2) #ruby=1.9.3-p125 - a comment when you want to use ruby code for ruby or when you want to specify patchlevel or gemset!:
#ruby=1.9.3
ruby ENV['RUBY_VERSION'] || '1.9.3'
Will allow bundler to work with any ruby loaded by RVM but by default will use 1.9.3 from #ruby=

How do I add conditional rubygem requirements to a gem specification?

Is it possible to add a gem dependency only if the person is using a certain version of ruby?
Background: I'm working on a fork of a project that uses Test::Unit::Autorunner and the like. They are part of the standard library in ruby 1.8, but aren't part of the standard library in 1.9.1, and is instead in the "test-unit" gem. I want to add a dependency that says that if someone's using ruby 1.9.1 or later, install the "test-unit" gem, but if they're using 1.8 or earlier, they don't need to install anything.
If you look at the gemspec documentation for add_dependency, there isn't an option for a ruby version. Perhaps you could use the post_install_message attribute to tell the user to install the gem if they're using ruby 1.9.
I did this exact thing for a project. The trick is to add the script as an extension, which will then get executed at install time on the user's machine.
Here are code snippets and links to our github:
First, when in the gemspec (we're actually using a Rakefile to generate it, but the result ends up the same) source
# This file *needs* to be named this, there are other files
# for other extension processors
s.extensions << 'ext/mkrf_conf.rb'
And then the relevant lines in that mkrf_conf.rb source
require 'rubygems/dependency_installer.rb'
inst = Gem::DependencyInstaller.new
inst.install "test-unit" if RUBY_VERSION > "1.9"
Gem doesn't support conditional dependencies (except on gem builder's environment -as noted above), and bundler is not a viable option to solve this either - see https://github.com/carlhuda/bundler/issues/1281
hay ... i'm kind of a ruby newbie ... if this is the best way to do it.
any way ... i wish i can do that using only Ruby .... though u can use your operating system shell to do that, by using this in your program installer, just execute (works for Linux based operating systems):
$ruby --version
(u can execute that from a ruby installer file, just like: ruby --version)
and put a possibility according to output, if it's 1.9.1 add an extra line to execute:
$ sudo gem install gem_name
else, just leave it be.
Checkout this tutorial in the Ruby Programming wikibook.
Tt shows how to install different versions of dependencies depending on what version of ruby the installee is using.
(short answer--it ain't as easy as it should be)
You can't. You need to build two gems, one with
spec.required_ruby_version = '~> 1.8.6'
and one with
spec.required_ruby_version = '~> 1.9.1'
spec.add_dependency 'test-unit', '~> 2.0.5'
Gemspecs are just ruby files anyway, so you can execute any ruby code inside them, so:
spec.add_dependency = 'test-unit', '>= 2.0' if RUBY_VERSION =~ '1.9'
EDIT: Specs run only on the builders machine.

Resources