Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to run IRB.start in context of current class

Tags:

ruby

irb

I've been just going through PragProg Continuous Testing With Ruby, where they talk about invoking IRB in context of current class to inspect the code manually.

However, they quote that if you invoke IRB.start in a class, self is predefined, and refers to the object we were in when start was called which isn't true in my case.

Even for very simple example like

a = "hello" require 'irb' ARGV.clear # otherwise all script parameters get passed to IRB IRB.start 

When I try to access the a variable, I get the obvious

NameError: undefined local variable or method `a' for main:Object 

It works only when I change a to global variable

$a = "hello" require 'irb' ARGV.clear # otherwise all script parameters get passed to IRB IRB.start 

then I can access it

irb(main):001:0> $a => 1 

Is there any way around this to access local and instance variables in the current class?

like image 265
Jakub Arnold Avatar asked Nov 15 '10 23:11

Jakub Arnold


People also ask

How do I run an IRB?

Starting and Stopping IRB You can start it on any computer where Ruby is installed by executing the command irb from your command line interface. The prompt indicates that you're running IRB and that anything you execute will run in the main context, which is the top-level default context of a Ruby program.

How do I open IRB in terminal?

To access IRB, just type irb in the terminal. IRB allows you to do anything you can do in a Ruby file. For instance, you can do math, get the time by typing Time. now , or print text to the screen.

How do I load files into IRB?

If you only need to load one file into IRB you can invoke it with irb -r ./your_file. rb if it is in the same directory. This automatically requires the file and allows you to work with it immediately. If you want to add more than just -r between each file, well that's what I do and it works.


2 Answers

As you've already discovered, self does not refer to the object where IRB was started, but to the TOPLEVEL_BINDING, which seems to be an instance of the Object class itself.

You can still run an IRB session with a specific class or object as the context, but it's not as simple as just starting IRB.

If you care about is starting IRB with a specific context, then it's really easy to do when you're starting IRB manually. Just start IRB normally and then call the irb method, passing it the object/class you want as the context.

$ irb irb(main):002:0> require 'myclass' => true irb(main):003:0> irb MyClass irb#1(MyClass):001:0> self => MyClass 

You can also start an IRB session programmatically and specify the context, but it's not nearly as easy as it should be because you have to reproduce some of IRB's start-up code. After a lot of experimenting and digging around in the IRB source code, I was able to come up with something that works:

require 'irb' IRB.setup nil IRB.conf[:MAIN_CONTEXT] = IRB::Irb.new.context require 'irb/ext/multi-irb' IRB.irb nil, self 
like image 120
bryant Avatar answered Oct 14 '22 11:10

bryant


I'd suggest trying this in ripl, an irb alternative. The above example works:

a = 'hello' require 'ripl' Ripl.start :binding => binding 

Note that local variables work because your passing the current binding with the :binding option.

You could possibly do the same in irb, but since it's poorly documented and untested, your chances of doing it cleanly are slim to none.

like image 42
cldwalker Avatar answered Oct 14 '22 11:10

cldwalker