Cobwwweb logo

Add a Console to your Ruby Project

Aug 06, 2018 Ruby

The Rails console is a really powerful way to interact with your Rails applications via the command line. And when I started writing Ruby applications (without Rails) it was something I immediately missed dearly. But, as it turns out, those feelings I had were unfounded, as it's quite easy to add a console to your project.

Under the hood the Rails console uses IRB. You may remember IRB from your early days learning Ruby. IRB stands for interactive Ruby. All it does is provide a way for you to execute ruby expressions on the command line – it provides a shell in a ruby environment.

If you have Ruby installed on your machine, then you have IRB. And you can start IRB by running the irb command:

$ irb

And then you can run ruby as you would within any ruby file, and the code is processed immediately.

irb(main):001:0> def add(n1, n2)
irb(main):002:1> n1 + n2
irb(main):003:1> end
=> :add
irb(main):004:0> add(1, 1)
=> 2
irb(main):005:0> add(2, 3)
=> 5

All Rails console does is load an IRB instance that has access to your project's code. So, really, that's all we need to do to get IRB running in your Ruby project.

Let's take a really simple Ruby project. It'll have a single class – Calculator – that will add and subtract two numbers. And we will put that file in our lib directory within our project. Our class will look like this:

lib/calculator.rb

class Calculator

  def add(n1, n2)
    n1 + n2
  end

  def subtract(n1, n2)
    n1 - n2
  end

end

Pretty simple, right? Good.

Now, from the command line within that project, let's open an IRB instance:

$ irb

And within IRB, let's create a new calculator:

irb(main):001:0> calc = Calculator.new
Traceback (most recent call last):
        2: from /Users/seancdavis/.rbenv/versions/2.5.1/bin/irb:11:in `<main>'
        1: from (irb):1
NameError (uninitialized constant Calculator)

Hmmm … IRB doesn't know what Calculator is. Why not? When we open an IRB instance on our machine, it's thinking globally. We haven't provided any context in which to open the session. We can change that by loading our files first.

Let's create a ruby command-line script to open a console session. We're going to put this file in the bin directory.

In its simplest form, this file will look like this:

bin/console

#!/usr/bin/env ruby

require 'irb'

IRB.start

I like to make these files executable so we don't have to use the ruby command to run them:

$ chmod +x bin/console

And then we can start our IRB session by running the new console script.

$ bin/console

And we can try to instantiate a calculator instance again:

irb(main):001:0> calc = Calculator.new
Traceback (most recent call last):
        2: from bin/console:5:in `<main>'
        1: from (irb):1
NameError (uninitialized constant Calculator)

Dang! Same issue.

What we're missing this time is loading the calculator class prior to opening the IRB session. We can do this using the require method. But we can't just use require because our ruby doesn't inherently know where the Calculator class is. Instead we can use require_relative and point relatively to that file, like so:

bin/console

#!/usr/bin/env ruby

require 'irb'
require_relative '../lib/calculator'

IRB.start

Now, let's try that again:

irb(main):001:0> calc = Calculator.new
=> #<Calculator:0x00007fb38d8bc520>
irb(main):002:0> calc.add(1, 2)
=> 3
irb(main):003:0> calc.subtract(2, 1)
=> 1

And look at that – it works!

As your project gets larger, as long as you require your main file in your console script, you'll be able to open interactive sessions with access to all your code.


Bonus! I have a follow-up article in which you can add a reload! method to your console so you don't have to restart the console session every time you make a change in your project.

Did you learn something or find this article interesting?

If so, why not