module Cleanroom::ClassMethods

Class methods

Private Class Methods

class_eval() click to toggle source
# File lib/cleanroom.rb, line 109
def class_eval
  raise Cleanroom::InaccessibleError.new(:class_eval, self)
end
instance_eval() click to toggle source
# File lib/cleanroom.rb, line 113
def instance_eval
  raise Cleanroom::InaccessibleError.new(:instance_eval, self)
end

Public Instance Methods

evaluate(instance, *args, &block) click to toggle source

Evaluate the string or block in the context of the cleanroom.

@param [Class] instance

the instance of the class to evaluate against

@param [Array<String>] args

the args to +instance_eval+

@param [Proc] block

the block to +instance_eval+
# File lib/cleanroom.rb, line 69
def evaluate(instance, *args, &block)
  cleanroom.new(instance).instance_eval(*args, &block)
end
evaluate_file(instance, filepath) click to toggle source

Evaluate the file in the context of the cleanroom.

@param [Class] instance

the instance of the class to evaluate against

@param [String] filepath

the path of the file to evaluate
# File lib/cleanroom.rb, line 53
def evaluate_file(instance, filepath)
  absolute_path = File.expand_path(filepath)
  file_contents = IO.read(absolute_path)
  evaluate(instance, file_contents, absolute_path, 1)
end
expose(name) click to toggle source

Expose the given method to the DSL.

@param [Symbol] name

# File lib/cleanroom.rb, line 78
def expose(name)
  unless public_method_defined?(name)
    raise NameError, "undefined method `#{name}' for class `#{self.name}'"
  end

  exposed_methods[name] = true
end
exposed_methods() click to toggle source

The list of exposed methods.

@return [Hash]

# File lib/cleanroom.rb, line 91
def exposed_methods
  @exposed_methods ||= from_superclass(:exposed_methods, {}).dup
end

Private Instance Methods

cleanroom() click to toggle source

The cleanroom instance for this class. This method is intentionally NOT cached!

@return [Class]

# File lib/cleanroom.rb, line 103
def cleanroom
  exposed = exposed_methods.keys
  parent = self.name || 'Anonymous'

  Class.new(Object) do
    class << self
      def class_eval
        raise Cleanroom::InaccessibleError.new(:class_eval, self)
      end

      def instance_eval
        raise Cleanroom::InaccessibleError.new(:instance_eval, self)
      end
    end

    define_method(:initialize) do |instance|
      define_singleton_method(:__instance__) do
        unless caller[0].include?(__FILE__)
          raise Cleanroom::InaccessibleError.new(:__instance__, self)
        end

        instance
      end
    end

    exposed.each do |exposed_method|
      define_method(exposed_method) do |*args, &block|
        __instance__.public_send(exposed_method, *args, &block)
      end
    end

    define_method(:class_eval) do
      raise Cleanroom::InaccessibleError.new(:class_eval, self)
    end

    define_method(:inspect) do
      "#<#{parent} (Cleanroom)>"
    end
    alias_method :to_s, :inspect
  end
end
from_superclass(m, default = nil) click to toggle source

Get the value from the superclass, if it responds, otherwise return default. Since class instance variables are not inherited upon subclassing, this is a required check to ensure subclasses inherit exposed DSL methods.

@param [Symbol] m

the name of the method to find

@param [Object] default

the default value to return if not found
# File lib/cleanroom.rb, line 156
def from_superclass(m, default = nil)
  return default if superclass == Cleanroom
  superclass.respond_to?(m) ? superclass.send(m) : default
end