The Different Ways of Pry and Irb

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.

Navigation

%d bloggers like this: