如何在当前类的上下文中运行IRB.start

Jak*_*old 27 ruby irb

我一直在使用Ruby进行PragProg 连续测试,在那里他们讨论IRB在当前类的上下文中调用以手动检查代码.

但是,他们引用如果你IRB.start在一个类中调用,self是预定义的,并引用我们在调用start时所在的对象,这在我的情况下是不正确的.

即使是非常简单的例子

a = "hello"
require 'irb'
ARGV.clear # otherwise all script parameters get passed to IRB
IRB.start
Run Code Online (Sandbox Code Playgroud)

当我尝试访问a变量时,我明白了

NameError: undefined local variable or method `a' for main:Object
Run Code Online (Sandbox Code Playgroud)

它仅在我更改a为全局变量时有效

$a = "hello"
require 'irb'
ARGV.clear # otherwise all script parameters get passed to IRB
IRB.start
Run Code Online (Sandbox Code Playgroud)

然后我可以访问它

irb(main):001:0> $a
=> 1
Run Code Online (Sandbox Code Playgroud)

有没有办法解决当前类中的本地和实例变量?

bry*_*ant 37

正如您已经发现的那样,self并没有引用IRB启动的对象,而是TOPLEVEL_BINDING引用了Object类,它似乎是类本身的一个实例.

您仍然可以使用特定的类或对象作为上下文运行IRB会话,但它并不像启动IRB那么简单.

如果您关心的是使用特定的上下文启动IRB,那么当您手动启动IRB时,这很容易.只需正常启动IRB,然后调用该irb方法,将您想要的对象/类作为上下文传递给它.

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

您也可以以编程方式启动IRB会话并指定上下文,但它并不像应该那么容易,因为您必须重现一些IRB的启动代码.在IRB源代码中进行了大量的实验和挖掘之后,我能够提出一些有效的方法:

require 'irb'
IRB.setup nil
IRB.conf[:MAIN_CONTEXT] = IRB::Irb.new.context
require 'irb/ext/multi-irb'
IRB.irb nil, self
Run Code Online (Sandbox Code Playgroud)

  • 恕我直言,回答这个问题的唯一答案. (5认同)

cld*_*ker 14

我建议用ripl来尝试这个,这是一种替代品.以上示例有效:

a = 'hello'
require 'ripl'
Ripl.start :binding => binding
Run Code Online (Sandbox Code Playgroud)

请注意,局部变量有效,因为您使用:binding选项传递当前绑定.

你可能会在irb中做同样的事情,但由于记录不完整且未经测试,你干净利落的机会很少.

  • 其次是避免IRB的建议.Pry是另一种选择. (2认同)

Ark*_*kku 10

您可以使用实例变量代替全局变量,例如:

require 'irb'
@a = "hello"
ARGV.clear
IRB.start

>> @a
=> "hello"
Run Code Online (Sandbox Code Playgroud)


hor*_*guy 10

使用Pry:

a = 'hello'
require 'pry'
binding.pry
Run Code Online (Sandbox Code Playgroud)


小智 6

以下是在调用IRB.start的上下文中从脚本调用IRB的方法.

require 'irb'
class C
    def my_method
        @var = 'hi'
        $my_binding = binding
        IRB.start(__FILE__)
    end
end

C.new.my_method
Run Code Online (Sandbox Code Playgroud)

执行脚本将调用IRB.当你到达提示时,你还有一件事要做......

% ./my_script.rb
irb(main):001:0> @var.nil?
=> true
irb(main):002:0> cb $my_binding
=> #<C:0x000000009da300 @var="hi">
irb(#<C:0x000000009da300>):003:0> @var.nil?
=> false
irb(#<C:0x000000009da300>):004:0> @var
=> "hi"
Run Code Online (Sandbox Code Playgroud)

请享用!

  • 那可能.但问题是,"如何在当前类的上下文中运行IRB.start".我的回答是唯一一个真正回答这个问题的人. (5认同)

Dav*_*son 5

从Ruby 2.4.0开始,您可以执行以下操作:

require 'irb'
binding.irb
Run Code Online (Sandbox Code Playgroud)

这将启动IBR REPL,您将在其中拥有正确的值,self并且将能够访问范围内的所有局部变量和实例变量。键入Ctrl + D或quit以便恢复您的Ruby程序。