module So::SpecObject

Public Class Methods

extended(mod) click to toggle source
# File lib/spec_object.rb, line 440
def self.extended(mod)
  mod.send(:define_singleton_method, :behaviours) do
    @behaviours ||= {}
  end

  mod.send(:define_method, :initialize) do |wrapped|
    @wrapped = wrapped
    @calls = []
  end

  mod.send(:define_method, :method_missing) do |name, *args|
    output = @wrapped.send(name, *args)

    behaviour = mod.behaviours[name]
    if behaviour
      v_args, v_output, expr = behaviour.values_at(:args, :output, :expr)

      expr =
        expr
          .substitute(v_output, output.to_so_expr)
          .substitute(v_args, args.to_so_expr)

      v = expr.evaluate(@calls)
      unless v.kind_of?(Const) && v.value
        puts v.pp(0)
        raise "Problem"
      end
    end

    @calls.push([name, args, output])

    output
  end
end

Public Instance Methods

behaviour(name, &blk) click to toggle source
# File lib/spec_object.rb, line 484
def behaviour(name, &blk)
  args = Variable.new
  output = Variable.new

  expr = DSL.new.instance_exec(args, output, &blk).to_so_expr

  behaviours[name] = {
    args: args,
    output: output,
    expr: expr
  }
end
specs(cl) click to toggle source
# File lib/spec_object.rb, line 475
def specs(cl)
  spec = self

  old_new = cl.method(:new)
  cl.send(:define_singleton_method, :new) do |*args|
    spec.new(old_new.call(*args))
  end
end