Reputation: 15940
I have a small Ruby script that I'm writing to automate the preparation of a development environment on local machines. Because I can't be certain that the rubyzip2
library is present on all of the machines, I'm having the script install it when needed.
Currently, my script is doing the following:
begin
require 'zip/zip'
rescue LoadError
system("gem install rubyzip2")
end
Once the gem has been installed, the script continues execution; however, the gem hasn't been loaded so all code requiring rubyzip2
halts the execution.
How do I load the gem into memory so that the script can continue running after installation?
Upvotes: 15
Views: 6393
Reputation: 708
With bundler version higher than 1.10 (to update just run gem install bundler
) you can use its new 'inline' feature as described here.
require 'bundler/inline'
gemfile(true) do
source 'https://rubygems.org'
gem 'catpix'
end
puts Catpix::VERSION
First parameter of gemfile
method is whether gems that aren't already installed on the user's system should be installed.
Upvotes: 7
Reputation: 10726
Instead of doing require 'thegem'
and rescuing error, you should check the gem availability before, and then, if needed, install it. After, you can require it.
Take a look at this post for the gem availability
Or this post
EDIT
After installation, you need to clear gem paths if you don't want to reload your script. You could achieve this with this method :
Gem.clear_paths
There are already answered questions here
So your code should looks like this ( for example ) :
begin
gem "rubyzip2"
rescue LoadError
system("gem install rubyzip2")
Gem.clear_paths
end
require 'zip/zip'
Upvotes: 18
Reputation: 1469
Ok so you may want to use Bundler and set up a Gemfile then have bundler do a bundle install, bundler will fetch out all the gems and install them if it is not already installed and you can then require all the gems in the gem file. Read the documentation in the link for more information.
But what you are looking to do specifically in your question is to use the retry keyword. This keyword will retry the loop after the rescue was called.
So if you require the gem and it fails and the Load Error Exception is called. The Begin Block will rescue, the system call will install the gem, then it will retry and require the gem. Just cautious because this may lead to an infinite loop unless you want to set up a condition to maybe retry it only once.
begin
require 'zip/zip'
rescue LoadError
system("gem install rubyzip2")
retry
end
Upvotes: 1