I've got a Rakefile with the following contents:
namespace :geo_data do
desc 'Imports geo data to Heroku'
task :heroku_import => :environment do
system "heroku pg:psql DATABASE -c 'DELETE FROM <table name>' -a <heroku app name>"
# some more stuff...
end
end
Whenever I run rake geo_data:heroku_import
, it'll crash on my Heroku command with this error:
Your Ruby version is 1.9.3, but your Gemfile specified 2.2.2
However, if I run the Heroku command - heroku pg:psql DATABASE -c 'DELETE FROM <table name>' -a <heroku app name>
- directly from the command line in a terminal window, it works fine.
So it would appear that the system
command is using a different version of Ruby.
Interestingly, as far as I can tell, I don't even have 1.9.3
installed on my machine. This is the output from rvm list
:
rvm rubies
ruby-2.0.0-p598 [ x86_64 ]
ruby-2.2.0 [ x86_64 ]
=* ruby-2.2.2 [ x86_64 ]
# => - current
# =* - current && default
# * - default
Based on that output, I don't have 1.9.3
installed and 2.2.2
is set as my current and default Ruby version.
Am I correct in determining that system
is using a different version of Ruby, or is there something else I'm missing? And if it is using a different version, how can I make it use 2.2.2
(or preferably whatever my default is currently set to)?
This is the contents of my Gemfile:
source 'https://rubygems.org'
ruby '2.2.2'
gem 'rails', '4.2.3'
gem 'rails-api'
gem 'spring', :group => :development
gem 'pg'
gem 'stripe'
gem 'jsonapi-resources', '0.7.0'
gem 'rails_api_auth'
gem 'rack-cors', require: 'rack/cors'
gem 'activerecord-postgis-adapter'
gem 'rgeo-geojson'
gem 'geocoder'
gem 'activerecord-import'
gem 'sidekiq'
gem 'unicorn'
group :development, :test do
gem 'rspec-rails'
gem 'forgery'
gem 'foreman'
end
group :development do
gem 'pry-rails'
end
There a few environment variables that Ruby will check when it is launched that you can use to control things like the load path and to set options.
Bundler is “infectious”, in that when you use it it adds some of these environment variables so that another Ruby process executed as a child will automatically try to use Bundler with the same Gemfile
.
Compare the output of ruby -e "puts ENV.inspect"
with bundle exec ruby -e "puts ENV.inspect"
inside a project using Bundler.
This is normally what you want to happen, so that you are always using the versions of Gems and Ruby defined in your Gemfile
.
The heroku
command includes its own installation of Ruby (it’s in /usr/local/heroku/ruby
on my machine) which it uses rather than your normal version. This is quite an old version of Ruby, mine is 1.9.3p194.
So when you use system
to run the heroku
command, the Ruby process that is created checks the environment variables and loads Bundler (using the Gem from the version of Ruby you’re using) and then tries to setup everything according to your Gemfile
. This is where the Ruby version mismatch happens.
To fix this, you need to tell Bundler not to include the various environment variables when launching a subprocess. There are a few methods that deal with this, in your case you want to use Bundler.clean_system
instead of plain system
:
Bundler.clean_system "heroku pg:psql DATABASE -c 'DELETE FROM <table name>' -a <heroku app name>"
This will allow the Heroku client to run without interference from Bundler and your Gemfile
.