Tom
Tom

Reputation: 15940

After installing a gem within a script, how do I load the gem?

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

Answers (4)

Aleksander Ryhlitski
Aleksander Ryhlitski

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

lcoq
lcoq

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

ericraio
ericraio

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

farnoy
farnoy

Reputation: 7776

Use Bundler with your application/library. This will allow users to run bundle and all the gems will be fetched and ready for you to use.

Upvotes: 1

Related Questions