Ruby - Digest::Digest is deprecated; Use Digest - ruby

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

Related

Get ruby gem version without installation

If I have a local gem (gemfile.gem) how can I get the name and version information from code or the command line without installing the gem.
Reason: I'm installing a user gem to validate it and want to uninstall it to clean up. User gem is not something I control so I can't depend on naming conventions.
CLI Solution:
gem spec gemfile.gem name
gem spec gemfile.gem version
Ruby Solution:
name = Psych.safe_load(`gem spec gemfile.gem name`).to_s
version = Psych.safe_load(`gem spec gemfile.gem version`, permitted_classes: [Gem::Version]).to_s
# Now you can uninstall the gem with
Gem::Uninstaller.new(name, {:version => version, :force => true}).uninstall
You can see locked version in Gemfile.lock
cat Gemfile.lock | grep gem-name
Other option, but need bundle install first
bundle exec gem dependency | grep gem-name
Update:
If you need to check local gem version, for example some-gem.gem, you can use such command to parse all information from binary
gem specification some-gem.gem
or just
gem spec some-gem.gem
You can also look it with Ruby format
gem spec some-gem.gem --ruby
Of course you can use grep to filter lines with version word
But it's better to pass it as argument like this
gem spec some-gem.gem version
Your question is ambiguous. If you mean "How can I read in the gem name and version from the gemspec?" then you can use the output of Gem::Specification#load. For example, assuming you have a gem with a standard layout and foo_bar.gemspec in the root of your gem's project directory, you can use Git to find the top-level of your project and read in the gemspec:
$ cd "$(git rev-parse --show-toplevel)
$ ruby -e 'puts Gem::Specification.load "#{File.basename Dir.pwd}.gemspec"'
#<Gem::Specification name=foo_bar version=0.1.0>
You can then parse the output with sed, awk, or cut.
A Gemfile does not (necessarily) specify an exact version of a dependency. It might specify nothing (i.e. "any version is fine"), or ~> 1.0 (i.e. >= 1.0 and < 2.0), or whatever. Also, dependency constraints might further restrict the valid range of versions.
I'm assuming that this isn't what you meant by your question. Instead, you'd like to know what exact versions of dependencies will be installed by running bundle install, given a Gemfile.lock.
One way to achieve this reliably (i.e. rather than using grep and eyeballing which line(s) are most relevant) is by parsing the Gemfile.lock:
require 'bundler'
lockfile = Bundler::LockfileParser.new(Bundler.read_file('Gemfile.lock'))
puts lockfile.specs.find { |spec| spec.name == 'the-gem-you-want-to-check' }.version

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.

How do I set RSpec to an earlier version?

Is there a way to use an earlier version of RSpec without uninstalling the default version? If not, what's the safest way to replace the current version? The uninstall/reinstall instructions linked to in this SO answer seem to be gone.
I'm trying to learn testing with RSpec, and all the tutorials I've found seem to predate 3.0. I invariably get deprecation warnings (if I'm lucky) or errors when using their old expectation syntax. I've relied heavily on this article to set me straight, but the time I spend updating the syntax in the tutorials' examples keeps me from concentrating on the substance of the lessons.
The same SO answer I linked to mentioned a config option in Rails' environment.rb file, but I'm not using Rails for the current tutorial, just Ruby and (eventually) Sinatra. I'm wondering if I can just add that file to be project folder.
I did add a Gemfile with the RSpec 2.1:
source 'https://rubygems.org'
gem 'rspec', '~> 2.10.0'
gem 'guard'
gem 'guard-rspec'
gem 'terminal-notifier'
gem 'terminal-notifier-guard'
The 2.1 installed after running bundle install, but after running bundle exec init and running my specs with the old syntax, I still get the same deprecation warnings and errors.

How do I get a list of gems that are installed that have native extensions?

I'm on windows, and have updated from ruby 1.8.x to 1.9.x, and am now getting error popups that complain ruby-mssomethingrt.1.8.x.dll is missing.
I would like to find out which gems have native extensions, so I can uninstall them and force a rebuild of the native extensions locally during installation again, to make the error go away.
Based on this answer, here is a solution that finds and offers to reinstall gems with native extensions that works with recent rubies (>=1.9).
native_gems = []
Gem::Specification.each do |spec|
native_gems << "#{spec.name}:#{spec.version}" unless spec.extensions.empty?
end
install_cmd = "gem install #{native_gems.join ' '}"
puts "Found #{native_gems.length} gem(s) with native extensions:"
puts "\n> " + install_cmd, "\nReinstall gems with above command? (yn)"
exec insall_cmd if gets.downcase[0] == 'y'
Example Output:
Found 36 gem(s) with native extensions:
> gem install atomic:1.1.13 bcrypt-ruby:3.0.1 bigdecimal:1.2.0 eventmachine:1.0.3 eventmachine:1.0.0 eventmachine:0.12.10 ffi:1.9.3 ffi:1.9.0 ffi:1.7.0 hiredis:0.4.5 hpricot:0.8.6 io-console:0.4.2 json:1.8.1 json:1.8.0 json:1.7.6 nokogiri:1.6.0 nokogiri:1.5.9 pg:0.17.1 pg:0.17.0 pg:0.16.0 pg:0.15.1 pg:0.13.2 psych:2.0.0 puma:2.7.1 puma:2.6.0 puma:2.4.0 puma:1.6.3 sqlite3:1.3.8 sqlite3:1.3.7 sqlite3:1.3.5 therubyracer:0.12.0 thin:1.5.1 thin:1.5.0 thin:1.4.1 websocket-driver:0.2.3 websocket-driver:0.1.0
Reinstall gems with above command? (yn)
…
A good start would be to look at the gem specification for each gem and see if it has the extensions field set. That should leave you with a short-list of gems to re-install. They don't necessarily all use native extensions, but if you look at the corresponding extconf.rb files, this should be pretty easy to find out.
Update: Here is a short ruby script to list those gems:
require 'rubygems'
Gem.source_index.each do |gem|
spec = Gem.source_index.specification(gem[0])
ext = spec.extensions
puts "#{gem[0]} has extensions: #{ext}" unless ext.empty?
end
You can rebuild (and restore to a pristine state) all installed gems with:
gem pristine --all
--all --no-extensions will restore gems without extensions, but despite being documented, --extensions appears to have no effect (at least on rubygems 1.8.23 on Ubuntu 12.10).
In Cygwin you could try gem list --all -d | grep --before-context=1 --after-context=4 Platform.
gem list
the part after the version next to the gem should indicate whether it's running native code:
e.g. json (1.4.6 x86-mingw32)
The error you are seeing is because one of the gems you are using expects the 1.8 ruby interpreter to be present which it no longer is (as you have upgraded to 1.9).
I would have thought that just running 'gem update' would fix your problem. If it doesn't, then you might need to seek an alternative gem for the one that is expecting the ruby 1.8 interpreter to be present.
Onliner for bundler + rails:
rails r "puts Gem::Specification.select{|i| i.extensions.any?}.map(&:name)"
prints out all native code gems (which usually need updates when updating major Ruby versions)

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