I need to call a ruby script2.rb using Bundler + Gemfile from another ruby script1.rb using Bundler + Gemfile.
I noticed that the Gems available to script2.rb are only those of script1.rb. The gems unique to script2.rb are not available when script2.rb is called by script1.rb. When script2.rb is called directly from the bash shell, everything is available.
I made sure it's not an ENV problem, I compared them using diff with helper code like so in both files and made a couple modifications to make them match.
File.open("script2_env.txt", 'wb') {|f| f.write(JSON.pretty_generate(ENV.to_h))}
To make sure it was not a $LOAD_PATH problem, I also made sure they match.
In script2.rb, which is called by script1.rb, I added the following line to match the $LOAD_PATH of script1 :
$:.unshift "/usr/local/Cellar/rbenv/1.1.2/rbenv.d/exec/gem-rehash"
My understanding of the problem is that somehow Bundler is not initialized properly when script2.rb is called from script1.rb, maybe because there is no
eval "$(rbenv init -)"
as there is in my bash_profile
script1/script1.rb :
#!/usr/bin/env ruby
cwd=Dir.pwd ; ourDir=File.dirname(__FILE__) ; Dir.chdir(ourDir)
require 'bundler' ; Bundler.setup
require "awesome_print"
ap "in script1, we have awesome_print in our GemFile"
exec("/Users/charbon/wip/script2/script2.rb")
script1/Gemfile
source 'https://rubygems.org'
gem 'awesome_print'
script2.rb :
#!/usr/bin/env ruby
puts "we are now in script2.rb"
$:.unshift "/usr/local/Cellar/rbenv/1.1.2/rbenv.d/exec/gem-rehash"
cwd=Dir.pwd ; ourDir=File.dirname(__FILE__) ; Dir.chdir(ourDir)
#make ENV match to script1 ENV
ENV.delete('BUNDLER_ORIG_GEM_PATH')
ENV['BUNDLE_GEMFILE']=ourDir+"/Gemfile"
ENV['RBENV_DIR']=ourDir
require 'bundler' ;
Bundler.setup
require 'awesome_print'
ap "in script2, we also have awesome_print in our GemFile"
puts "but we also have colored, which is not available, this throws an erro"
require "colored"
script2/Gemfile
source 'https://rubygems.org'
gem 'awesome_print'
gem 'colored'
The result is
/Users/charbon/wip/script1/script1.rb
"in script1, we have awesome_print in our GemFile"
we are now in script2.rb
ourDir is /Users/charbon/wip/script2
"in script2, we also have awesome_print in our GemFile"
but we also have colored, which is not available, this throws an error
/Users/charbon/wip/script2/script2.rb:19:in `require': cannot load such file -- colored (LoadError)
from /Users/charbon/wip/script2/script2.rb:19:in `<main>'
script1.rb
#!/usr/bin/env ruby
cwd=Dir.pwd ; ourDir=File.dirname(__FILE__) ; Dir.chdir(ourDir)
require 'bundler' ; Bundler.setup
require "awesome_print"
ap "in script1, we have awesome_print in our GemFile"
Bundler.with_clean_env do
Dir.chdir('/Users/charbon/wip/script2/script2.rb') do
exec("./script2.rb")
end
end
script2.rb
#!/usr/bin/env ruby
puts "we are now in script2.rb"
cwd=Dir.pwd ; ourDir=File.dirname(__FILE__) ; Dir.chdir(ourDir)
require 'bundler' ;
Bundler.setup
require 'awesome_print'
ap "in script2, we also have awesome_print in our GemFile"
puts "but we also have colored, which is not available, this throws an erro"
require "colored"
From my comment on the original question:
Bundler supports inline Gemfiles which allow you to specify your required gems (and sources!) directly in your ruby script. As long as you have bundler installed on the machine it should work, allowing you to keep your script dependencies isolated.
Bundler will handle installing & requiring the required gems, allowing you to run your script
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With