class QED::Scope

Scope is the context in which QED documents are run.

Constants

DIRECTORY

Location of ‘qed/scope.rb`.

Public Class Methods

new(demo, options={}) click to toggle source

Setup new Scope instance.

Calls superclass method
# File lib/qed/scope.rb, line 13
def initialize(demo, options={})
  super()

  @_applique = demo.applique_prime

  @_file     = demo.file
  @_root     = options[:root] || $ROOT  # FIXME

  @_features = []

  include *demo.applique

  # TODO: custom extends?

  __create_clean_binding_method__
end

Public Instance Methods

After(type=:each, &procedure) click to toggle source

Define “after” advice. Default type is :each, which evaluates just after example code is run.

# File lib/qed/scope.rb, line 96
def After(type=:each, &procedure)
  type = :step if type == :each
  type = :demo if type == :all
  @_applique.After(type, &procedure)
end
Before(type=:each, &procedure) click to toggle source

Define “before” advice. Default type is :each, which evaluates just before example code is run.

# File lib/qed/scope.rb, line 88
def Before(type=:each, &procedure)
  type = :step if type == :each
  type = :demo if type == :all
  @_applique.Before(type, &procedure)
end
Data(file) { || ... } click to toggle source

Read a static data file and yield contents to block if given.

This method no longer automatically uses YAML.load.

# File lib/qed/scope.rb, line 152
def Data(file) #:yield:
  file = Dir.glob(File.join(File.dirname(@_file), file)).first || file
  #case File.extname(file)
  #when '.yml', '.yaml'
  #  data = YAML.load(File.new(file))
  #else
    data = File.read(file)
  #end
  if block_given?
    yield(data)
  else
    data
  end
end
Table(file=nil, options={}) { || ... } click to toggle source

Use sample table to run steps. The table file is located relative to the demo, failing that it will be looked for relative to the working directory.

# File lib/qed/scope.rb, line 119
def Table(file=nil, options={}) #:yield:
  if file
    file = Dir.glob(File.join(File.dirname(@_file), file)).first || file
  else
    file = @_last_table
  end
  @_last_table = file

  file_handle = File.new(file)

  if options[:stream]
    if block_given?
      YAML.load_documents(file_handle) do |data|
        yield data
      end
    else
      YAML.load_stream(file_handle)
    end
  else
    if block_given?
      tbl = YAML.load(file_handle)
      tbl.each do |data|
        yield(*data)
      end
    else
      YAML.load(file_handle)
    end
  end
end
When(*patterns, &procedure) click to toggle source

Define “when” advice.

# File lib/qed/scope.rb, line 81
def When(*patterns, &procedure)
  #patterns = patterns.map{ |pat| pat == :text ? :desc : pat }
  @_applique.When(*patterns, &procedure)
end
__DIR__(file=nil) click to toggle source

Directory of current document.

# File lib/qed/scope.rb, line 103
def __DIR__(file=nil)
  if file
    Dir.glob(File.join(File.dirname(@_file), file)).first || file
  else
    File.dirname(@_file)
  end
end
__create_clean_binding_method__() click to toggle source

This turns out to be the key to proper scoping.

# File lib/qed/scope.rb, line 31
def __create_clean_binding_method__
  module_eval %{
    def __binding__
      @__binding__ ||= binding
    end
  }
end
clear_working_directory!() click to toggle source

Helper method to clear temporary work directory.

# File lib/qed/scope.rb, line 169
def clear_working_directory!
  dir = @_root
  dir = File.expand_path(dir)

  if dir == '/' or dir == File.expand_path('~')
    abort "DANGER! Trying to use home or root as a temporary directory!"
  end

  entries = Dir.glob(File.join(dir, '**/*'))

  dirs, files = entries.partition{ |f| File.directory?(f) }

  files.each { |file| FileUtils.rm(file)   }
  dirs.each  { |dir|  FileUtils.rmdir(dir) }
end
const_missing(const) click to toggle source

Redirect constant missing to toplevel (i.e. Object). This is to allow the evaluation scope to emulate the toplevel.

# File lib/qed/scope.rb, line 192
def const_missing(const)
  Object.const_get(const)
end
demo_directory() click to toggle source

Expanded dirname of file.

# File lib/qed/scope.rb, line 46
def demo_directory
  @_demo_directory ||= File.expand_path(File.dirname(@_file))
end
evaluate(code, file=nil, line=nil) click to toggle source

Evaluate code in the context of the scope’s special binding. The return value of the evaluation is stored in ‘@_`.

# File lib/qed/scope.rb, line 53
def evaluate(code, file=nil, line=nil)
  if file
    @_ = eval(code, __binding__, file.to_s, line.to_i)
  else
    @_ = eval(code, __binding__)
  end
end
include(*modules) click to toggle source
Calls superclass method
# File lib/qed/scope.rb, line 40
def include(*modules)
  super(*modules)
  extend self  # overcome dynamic inclusion problem
end
utilize(file) click to toggle source

Utilize is like require, but will evaluate the script in the context of the current scope.

# File lib/qed/scope.rb, line 66
def utilize(file)
  file = Dir[DIRECTORY + "/helpers/#{file}"].first
  if !file
    require 'plugin'
    file = Plugin.find("#{file}{,.rb}", :directory=>nil)
  end
  if file && !@_features.include?(file)
    code = File.read(file)
    evaluate(code, nil, file)
  else
    raise LoadError, "no such file -- #{file}"
  end
end