On Fri, Feb 6, 2009 at 11:55 AM, Jonathan Wills <runningwild / gmail.com> wrote:
>>
>> Because eval creates a new nested scope rather than sharing the
>> enclosing scope.
>>
>> Variable visibility between nested scopes is like a one-way mirror:
>> you can manipulate variables created in a parent scope but you can not
>> see or manipulate variables created in a 'child' scope.
>
> Ok, I see that now, good to know.  Now I have another question.  I want
> to be able to create an arbitrary number of 'clean' bindings in which I
> can run ruby code.  Basically I want the user to be able to supply an
> unspecified number of ruby files, all of which will get run, and not
> have to worry about namespace collisions.  Additionally I want access to
> the scopes that those files were executed in after they are done.  I
> know I can create a binding from my current scope, but if I put anything
> in it, it can get modified when I do my_binding.eval.

You can get a binding from any object that has a method to tell you
its binding. Something like this (off the top of my head) might work:
---
class ExecutionContext
  private_class_method :new

  @@contexts = {}

  def self.[](key)
    @@contexts[key]
  end

  def self.new_binding(key)
    new(key).binding
  end

  def initialize(key)
    raise KeyError if @@contexts[key]
    @@contexts[key] = self
  end

  def get_binding
    binding
  end
end
---

So, when you want a new binding to use, you call
ExecutionContext.new_binding(key), and to get back the a binding used
previously, you call ExecutionContext[key].get_binding, where "key" is
the key given when you called new_binding to generate the binding.

But while these are mostly "fresh" bindings, they are nothing at all
like safe sandboxes. You may need something like this:
http://github.com/why/sandbox/tree/master