There are a lot of ways to launch a Ruby or Rails console: irb, bundle exec irb, bundle console, and rails console are some of the most common. They seem similar, but they each work a little bit differently.

If you don’t know what those differences are, you’ll have some problems. Maybe you won’t be able to get your ActiveRecord models connected to the database. Or you’ll require a file and get the wrong version. Or a library you thought would be avaliable, wasn’t.

How do you make sure you’re using the right console at the right time?

Bundler vs non-Bundler

irb is just a plain Ruby console. It doesn’t care about your Gemfile. It doesn’t load anything but the core Ruby libraries. Anything else you want, you have to require.

If you install a gem using gem install, you can require it inside irb. If you used bundle install, you might be able to require it, depending on where Bundler put it. (Bundler will sometimes put gems outside of Ruby’s gem path, if you run something like bundle install --path or bundle install --deployment).

Since irb ignores your Gemfile, the versions inside your Gemfile.lock don’t matter. irb will load the newest version of a gem it can find:

1
2
3
4
5
6
7
8
9
10
11
12
13
~/Source/testapps/consoles[master *] jweiss$ gem list rails

*** LOCAL GEMS ***
rails (4.2.0.beta2, 4.2.0.beta1, 4.1.5, 4.1.1)

~/Source/testapps/consoles jweiss$ cat Gemfile | grep rails
gem 'rails', '4.1.5'

~/Source/testapps/consoles jweiss$ irb
irb(main):001:0> require 'rails'
=> true
irb(main):002:0> Rails.version
=> "4.2.0.beta2"

This can cause really weird problems with your code, if you’re not expecting it.

irb is great if you’re messing with core Ruby files. It’s fast, and doesn’t need any setup.

But if you want to use your Gemfile when you run a console, run bundle exec irb instead. The bundle exec allows irb to load the gems that Bundler knows about, and only the gems Bundler knows about:

1
2
3
4
5
~/Source/testapps/consoles jweiss$ bundle exec irb
irb(main):001:0> require 'rails'
=> true
irb(main):002:0> Rails.version
=> "4.1.5"

We got exactly the Rails version we were looking for.

bundler/setup vs Bundler.require

When would you run bundle console instead of bundle exec irb?

bundle exec irb sets things up so you can only require the gems in your Gemfile.lock.

bundle console goes one step further. When you run bundle console, you don’t even need to require the gems in your Gemfile. They’re already required for you:

1
2
3
4
5
6
7
8
9
~/Source/testapps/consoles jweiss$ bundle exec irb
irb(main):001:0> Rails.version
NameError: uninitialized constant Rails
  from (irb):1
  from /usr/local/bin/irb:11:in `<main>'

~/Source/testapps/consoles jweiss$ bundle console
irb(main):001:0> Rails.version
=> "4.1.5"

You could also get this behavior if you called Bundler.require inside your bundle exec irb console. Any gem in your Gemfile that isn’t marked require: false will be automatically required, and you’ll be able to use it without any extra work. When you’re working on projects with a Gemfile, that’s incredibly convenient.

Accessing Rails

There’s still one difference to think about: bundle console and rails console.

1
2
3
4
5
6
7
8
~/Source/testapps/consoles jweiss$ bundle console
irb(main):001:0> Rails.application
=> nil

~/Source/testapps/consoles jweiss$ rails console
Loading development environment (Rails 4.1.5)
irb(main):001:0> Rails.application
=> #<Consoles::Application:0x007f8db4d5ab30 @_all_autoload_paths=["/Users/jweiss...

bundle console just requires a bunch of gems. rails console requires those gems, but it will also load your entire Rails environment, set up autoloading, initialize your application, and give you a full Rails environment to play around in.

You can get something like the Rails console from bundle console if you require config/environment.rb:

1
2
3
4
5
6
7
~/Source/testapps/consoles jweiss$ bundle console
irb(main):001:0> Rails.application
=> nil
irb(main):002:0> require_relative 'config/environment.rb'
=> true
irb(main):003:0> Rails.application
=> #<Consoles::Application:0x007fd264f0b7c8 @_all_autoload_paths=["/Users/jweiss...

Each one, just a little more complicated

So, to recap:

  • irb is the basic Ruby console. It ignores your Gemfile, and only core Ruby classes are accessible without require-ing them. It can’t easily load gems that Bundler installs outside of RubyGems’ load path.

  • bundle exec irb is like irb, if you also required bundler/setup. You can only easily require gems that are in your Gemfile.lock, but you can load those gems no matter where Bundler put them.

  • bundle console is like bundle exec irb, if you also called Bundler.require. All of the gems in your Gemfile, except the ones marked require: false, can be used without requiring them. It’s really convenient when you’re writing your own gems, or working on non-Rails code.

  • rails console is like running bundle console inside a Rails app, if you also required config/environment.rb. You can play with your entire Rails app, autoloads and database connections work, and everything’s hooked up the way you’d expect. If you’re working in a Rails app, this is the most helpful kind of console.

There aren’t too many differences between these consoles. And while most of those differences won’t be too big (Oh, this file isn’t required? Better require it!), others will be totally infuriating if you don’t know what’s going on. (WHY IS THIS LOADING THE WRONG VERSION OF RAKE AGAIN!?)

But if you know the idea behind each of these consoles, you’ll be able to use the right kind of console at the right time. And all the libraries you need will be close by when you need them.

Did you like this post? You should read these:

Finished another Rails tutorial and still don’t know how to start?

Have you slogged through the same guide three times and still can't retain enough to write apps on your own?

In my free 7-part course, you’ll discover the fastest way to learn and remember new Rails ideas, so you can use them when you need them. And you'll learn to use what you already know to build your own Rails project.



Comments