27

私はちょうどRubyを使用したPragProg継続的テストIRBを行っています。そこでは、コードを手動で検査するために現在のクラスのコンテキストで呼び出すことについて話します。

ただし、IRB.startクラスで呼び出す場合、selfは事前定義されており、startが呼び出されたときに存在していたオブジェクトを参照していると彼らは引用しています。これは私の場合は当てはまりません。

のような非常に単純な例でも

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

変数にアクセスしようとするとa、明らかになります

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

aグローバル変数に変更した場合にのみ機能します

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

その後、私はそれにアクセスすることができます

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

現在のクラスのローカル変数とインスタンス変数にアクセスする方法はありますか?

4

9 に答える 9

39

すでに発見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

プログラムで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
于 2011-02-13T23:51:58.897 に答える
14

irbの代替手段であるriplでこれを試すことをお勧めします。上記の例は機能します:

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

:bindingオプションを使用して現在のバインディングを渡すため、ローカル変数が機能することに注意してください。

irbでも同じことを行うことができますが、文書化が不十分でテストされていないため、きれいに行う可能性はほとんどありません。

于 2010-11-16T00:12:54.087 に答える
11

グローバルの代わりに、インスタンス変数を使用できます。例:

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

>> @a
=> "hello"
于 2010-11-15T23:28:47.920 に答える
11

Ruby 2.4.0以降、これを行うことができます。

require 'irb'
binding.irb

これにより、IBR REPLが開始され、の正しい値が得selfられ、スコープ内にあるすべてのローカル変数とインスタンス変数にアクセスできるようになります。Ctrl + Dと入力するかquit、Rubyプログラムを再開します。

于 2017-01-12T03:14:34.927 に答える
10

Pryを使用する:

a = 'hello'
require 'pry'
binding.pry
于 2012-05-27T04:35:48.480 に答える
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

スクリプトを実行すると、IRBが呼び出されます。プロンプトが表示されたら、もう1つやることがあります...

% ./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"

楽しみ!

于 2011-08-13T04:46:14.243 に答える
2

Ruby2.2.3の私のソリューション。ブライアントと非常によく似ています

def to_s
  "Sample"
end

def interactive
  banana = "Hello"
  @banana = "There"
  require 'irb'
  IRB.setup(nil)
  workspace = IRB::WorkSpace.new(binding)
  irb = IRB::Irb.new(workspace)
  IRB.conf[:MAIN_CONTEXT] = irb.context
  irb.eval_input
end

irb(Sample):001:0> puts banana
Hello
=> nil
irb(Sample):002:0> puts @banana
There
=> nil
irb(Sample):003:0>

ローカル変数とインスタンス変数にアクセスできます。もちろん、ファイルのrequire 'irb'先頭に置くこともできます。との設定はbanana@bananairbプロンプトからアクセスできることを証明するためのものです。to_sはかなりのプロンプトを取得する1つの方法ですが、他の選択肢があります。また、別の方法を作成する本当の理由はありませんが、現状では、これをどこにでも配置でき、機能するはずです。

于 2015-12-05T04:05:39.870 に答える
0

ruby-debug-base gemは、binding_nメソッドをKernelモジュールに追加します。これにより、 evalで使用できるアクセスバインディングオブジェクトが提供され、コールスタック変数にアクセスできるようになります。Debugger.startを発行して、コールスタック追跡をオンにすることを忘れないでください。

これは、 irb(Rubyプログラム)内で何が起こっているかを内省するための使用法を示す例です。require 'sとDebugger.startを独自のRubyコード内に配置することもできます。

$ 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 > 

パッチを適用したバージョンのRubyfor1.9.2を実行する場合は、http://gitnub.com/rocky/rb-threadframeを参照して、コールスタックへのアクセスが改善されていると思います。Rubiniusは、 Rubinius::VM.backtraceを介して組み込まれたこの機能を提供します。

于 2010-12-22T10:30:02.530 に答える
0

これは、このスレッドのすべての回答のマッシュアップのようなものです。質問した人が要求した動作を生成する最小のコードです。

require 'irb'

module Craft
  class Console
    def start
      IRB.setup(__FILE__)
      workspace = IRB::WorkSpace.new(self)
      IRB::Irb.new(workspace).run(IRB.conf)
    end

    def hello
      puts 'hello world!'
    end
  end
end

をクリアする必要はなくARGV、明示的にを呼び出す必要もありませんeval_input

出力は次のようになります。

bundle exec craft console
irb(#<Craft::Console:0x00007fb0135592c0>):001:0>hello
hello world!
=> nil
于 2021-07-22T11:02:57.717 に答える