Class: YardExampleTest::Example::ConstantSandbox

Inherits:
Object
  • Object
show all
Defined in:
lib/yard_example_test/example/constant_sandbox.rb

Overview

Isolates constant definitions introduced during example evaluation

Resolves the top-level class or module for a YARD definition path, snapshots the constants on both +Object+ and that scope, yields control to the caller, then removes any constants that were added during the block. This prevents one example's constant definitions from leaking into subsequent examples.

Examples:

ConstantSandbox.new('MyClass#foo').isolate do |scope|
  # evaluate code that may define constants…
end
# any constants defined inside the block are now removed

Instance Method Summary collapse

Constructor Details

#initialize(definition) ⇒ ConstantSandbox

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Creates a sandbox for the given YARD definition path

Examples:

ConstantSandbox.new('MyClass#foo')

Parameters:

  • definition (String)

    a YARD path such as +"MyClass#method"+ or +"MyClass.method"+



30
31
32
# File 'lib/yard_example_test/example/constant_sandbox.rb', line 30

def initialize(definition)
  @scope = resolve_scope(definition)
end

Instance Method Details

#isolate {|scope| ... }

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method returns an undefined value.

Snapshots constants, yields the resolved scope, then cleans up

Any constants added to +Object+ or the resolved scope during the block are removed when the block returns (or raises), with one exception: constants added to +Object+ whose source file was newly loaded via +require+ during the block are preserved. This prevents one example's constant definitions from leaking into subsequent examples while still allowing +require+ calls to have their normal lasting effect (re-requiring a cached file would be a no-op, so stripping those constants would cause +NameError+ in later examples).

The resolved scope is yielded so that callers can use it as the evaluation binding.

Examples:

sandbox.isolate { |scope| scope.class_eval(code) }

Yields:

  • (scope)

    gives the resolved class/module (or +nil+) to the block

Yield Parameters:

  • scope (Class, Module, nil)

    the resolved scope constant



58
59
60
61
62
63
64
65
66
67
68
# File 'lib/yard_example_test/example/constant_sandbox.rb', line 58

def isolate
  global_before = Object.constants
  scope_before  = @scope.respond_to?(:constants) ? @scope.constants : nil
  loaded_before = $LOADED_FEATURES.dup

  yield @scope
ensure
  loaded_during = $LOADED_FEATURES - loaded_before
  clear_extra_constants(Object, global_before, skip_if_loaded_by: loaded_during)
  clear_extra_constants(@scope, scope_before) if scope_before
end