I ran into an interesting little problem when doing sone Ruby (and Rails) work today: I wanted to try something in pry
and, inside that Rails project I issued the following command:
$ pry -r sqlite3
…/gems/pry-0.14.1/lib/pry/pry_class.rb:103:in `require': cannot load such file -- sqlite3 (LoadError)
from …/gems/pry-0.14.1/lib/pry/pry_class.rb:103:in `block in load_requires'
from …/gems/pry-0.14.1/lib/pry/pry_class.rb:102:in `each'
from …/gems/pry-0.14.1/lib/pry/pry_class.rb:102:in `load_requires'
from …/gems/pry-0.14.1/lib/pry/pry_class.rb:143:in `final_session_setup'
from …/gems/pry-0.14.1/lib/pry/cli.rb:82:in `parse_options'
from …/gems/pry-0.14.1/bin/pry:12:in `<top (required)>'
from …/bin/pry:23:in `load'
from …/bin/pry:23:in `<main>'
from …/bin/ruby_executable_hooks:22:in `eval'
from …/bin/ruby_executable_hooks:22:in `<main>'
Interesting! I have both gems, pry
and sqlite3
installed. A similar attempt using irb
worked fine:
$ irb -r sqlite3
3.0.1 :001 > SQLite3::VERSION
=> "1.4.2"
3.0.1 :002 >
Maybe I confused the environment by setting some environment variable or other? With a newly opened command shell I got this:
$ pry -r sqlite3
[1] pry(main)> SQLite3::VERSION
=> "1.4.2"
[2] pry(main)>
Remarkable. In that new shell the irb
command behaved the same as before.
The only difference I could find was that the original call to pry
happened in a Rails project – which is using Bundler
to organise the Rubygems used in the project and resolve dependencies. As a small experiment I set up a minimal project that uses bundler and a rather short Gemfile
:
source "https://rubygems.org"
gem 'limit_detectors'
The gem ‘limit_detectors’ is one I wrote and I know that is doesn’t depend on other gems. Issuing the pry
command again … worked? Why? Some more investigation was needed…
Finally, I realised that another gem (Guard, to be specific), uses pry
. Therefore my Rails project’s development environment indirectly depends on pry
. It looks like pry
recognises that it’s running as part of a Bundler project, even when it is not explicitly called using bundle exec pry …
, which in turn causes it (pry) to ‘only’ recognise the gems that are also installed using Bundler. – And sqlite3
isn’t in this case, since I’m using PostgreSQL throughout.
Since irb
comes with the Ruby installation and is not part of the bundled gems, it ignores the bundler context when called like this:
irb -r sqlite3
However, explicitly calling it in the bundler context in a project that doesn’t depend on ‘sqlite3’ (directly or indirectly) will cause an error message:
$ bundle exec irb -r sqlite3
…/rubies/ruby-3.0.1/lib/ruby/3.0.0/irb/init.rb:376: warning: LoadError: cannot load such file -- sqlite3
3.0.1 :001 >
Nice! This is essentially the same problem, I faced at the very beginning, when pry
couldn’t find the sqlite3
gem.