How to run IRB.start in context of current class

后端 未结 8 1017
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-12-29 21:23

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

相关标签:
8条回答
  • 2020-12-29 22:24

    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
    
    0 讨论(0)
  • 2020-12-29 22:30

    The ruby-debug-base gem adds a binding_n method to the Kernel module and this will give you access binding object that can be used in an eval to give access to call-stack variables. Remember to issue Debugger.start to turn on call stack tracking.

    Here is an example showing its use to introspect what is going on inside irb (a Ruby program). One could put the require's and Debugger.start inside your own Ruby code as well.

    $ irb
    ruby-1.8.7-p302 > require 'rubygems'
     => true 
    ruby-1.8.7-p302 > require 'ruby-debug-base'
     => true 
    ruby-1.8.7-p302 > Debugger.start
     => true 
    ruby-1.8.7-p302 > puts caller
    /tmp/.rvm/rubies/ruby-1.8.7-p302/lib/ruby/1.8/irb/workspace.rb:52  :i  n `irb_binding' #`
    /tmp/.rvm/rubies/ruby-1.8.7-p302/lib/ruby/1.8/irb/workspace.rb:52
    => nil 
    ruby-1.8.7-p302 > eval "main", binding_n(2)
     => #<Object:0xb7762958 @prompt={:PROMPT_I=>"ruby-1.8.7-p302 > ", :PROMPT_N=>"  ruby-1.8.7-p302 ?> ", :PROMPT_S=>"ruby-1.8.7-p302%l> ", :PROMPT_C=>"ruby-1.8.7-p302 > ", :AUTO_INDENT=>true, :RETURN=>" => %s \n"}> 
    ruby-1.8.7-p302 > 
    

    If you are willing to run a patched version of Ruby for 1.9.2 see http://gitnub.com/rocky/rb-threadframe for what I think is better access to the call stack. Rubinius provides this capability built in via Rubinius::VM.backtrace.

    0 讨论(0)
提交回复
热议问题