1

私はRubyでスクリプトを評価していますが、各スクリプトに、というグローバル変数を持つ独自のサンドボックスを持たせたいと思います$window。変数は$window、スクリプトが実行されているサンドボックスに応じて異なるものを指す必要があります。スレッドローカル変数は機能しますが、私はスレッドを使用していません。私はRubyCAPIを使用しているので、可能性が少し広がります。

現在、私は各スクリプトを内で実行しているBindingので、そこではいくらかサンドボックス化されています。バインディングは閉じたローカル変数を持つことができますが、グローバル変数を持つことはできません。アイデアは次のとおりです。

sandbox1 = window1.get_binding
sandbox2 = window2.get_binding
sandbox3 = window3.get_binding

sandbox1.eval('$window.foo') # calls 'foo' on window 1
sandbox2.eval('$window.foo') # calls 'foo' on window 2
sandbox3.eval('$window.foo') # calls 'foo' on window 3

内のグローバル変数を閉じる方法はありますBindingか?私は可能な解決策を見つけて、それを以下に投稿しました。

4

2 に答える 2

1

さまざまなウィンドウがどのように関連付けられますか?

それらがスレッドにバインドされている場合、問題を解決する最も簡単な方法は、スレッドローカル変数を使用することです。他の何か(たとえば現在の時刻)にバインドされている場合は、グローバルハッシュを使用することをお勧めします。

私は個人的に専用のクラスに行き、後でリファクタリングしやすくします(グローバルは依存性注入が不十分なコードの臭いなので、おそらくこれをリファクタリングします):

class Windows < Hash
end
WINDOWS = Windows.new
...
window_scope = WINDOWS[Time.now].binding

次に、実際にはグローバルコレクションである可変定数があります。

于 2012-12-21T10:54:10.590 に答える
0

RubyCAPIを使用して可能な解決策を見つけました。バインディング内で評価されるものはすべて、そのバインディングの呼び出しフレームの下のどこかにあります。Ruby 1.8.7を使用すると、Cでこれを行うことができます。

public VALUE getCurrentWindow()
{
    // Get the current call frame from Ruby.
    FRAME* frame = ruby_frame;

    // Traverse up the call frame stack until we find a Window class.
    while (frame) {
        if (RTEST(rb_obj_is_kind_of(frame->self, rb_cWindow))
            return frame->self;

        frame = frame->prev;
    }

    // Couldn't find the window.
    return Qnil;
}

うまくいくようですが、問題が発生するかどうかを確認します。

于 2012-12-24T18:44:49.843 に答える