How to Run Irb.Start in Context of Current Class

How to run IRB.start in context of current class

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.

How does a new IRB session get its variable scope?

The Binding that is used to evaluate the code is set up in irb/workspace.rb:51 (I'm referring to Ruby 1.9.3 rev 35410 here):

@binding = eval("def irb_binding; binding; end; irb_binding",
TOPLEVEL_BINDING,
__FILE__,
__LINE__ - 3)

That means that your IRB session runs in the same context as code inside a top-level method. Observe:

puts "Outer object ID: %d" % self.object_id
puts "Outer binding: " + binding.inspect
smithy = Pirate.new
@blackbard = Pirate.new

def test
puts "Inner object ID: %d" % self.object_id
puts "Inner binding: " + binding.inspect
p @blackbard
p smithy
end
test

Output:

Outer object ID: 13230960
Outer binding: #<Binding:0x00000001c9aee0>
Inner object ID: 13230960
Inner binding: #<Binding:0x00000001c9acd8>
#<Pirate:0x00000001c9ada0>
/test.rb:18:in `test': undefined local variable or method `smithy' for main:Object (NameError)
...

Note that the object context (self) is the same both inside and outside the function. This is because every top-level method is added to the global main object.

Also note that the bindings inside and outside of the method differ. In Ruby, every method has its own name scope. This is why you can't access the local name from inside IRB, while you can access the instance variable.

To be honest, IRB is not the most glorious piece of Ruby software. I usually use Pry for this kind of stuff, using which you can just do:

require 'pry'
binding.pry

And have a session with access to the current local variables.

PRY or IRB - reload class and forget deleted functionality

You can use remove_const to remove the class from its parent, either from the Module it is in:

My::Module.send(:remove_const, :MyClass)

or from Object if it was not declared inside a Module:

Object.send(:remove_const, :MyClass)

How to use interactive_editor when REPL console is run in context of a particular object

I found a way around this:

def edit(*args)
system("$EDITOR #{args.join(' ')")
end

This still doesn't explain why I can't get this example to work with interactive_prompt.



Related Topics



Leave a reply



Submit