public
Last active

crashes ruby 1.9.3

  • Download Gist
gistfile1.txt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
# run with rspec filename.rb
require 'rspec'
# TODO: class vars?
# TODO: better just alias_method_chain method_missing for the duration of running the method
module Tdef
def self.check_args(args, rules)
rules.each_pair do |name, klass|
unless args[name.to_s].kind_of?(klass)
raise "Wrong type: #{name} should be #{klass.to_s}, but is #{args[name].class.to_s}"
end
end
end
def tdef name, args, &block
self.send(:define_method, name.to_sym) do |*arg_values|
raise "Wrong number of arguments" if args.count != arg_values.count
args_map = Hash.new
(0...arg_values.count).each do |i|
args_map[args.keys[i].to_s] = arg_values[i]
end
Tdef::check_args(args_map, args)
if self.class.respond_to?(:method_missing)
self.class.send(:alias_method, :method_missing_tmp, :method_missing)
end
self.class.send(:define_method, :method_missing) do |meth, *args, &block|
if args_map.keys.include?(meth.to_s)
args_map[meth.to_s]
else
method_missing_tmp meth, *args, &block
end
end
result = self.instance_eval &block
self.class.send(:remove_method, :method_missing)
if self.class.respond_to?(:method_missing_tmp)
self.class.send(:alias_method, :method_missing, :method_missing_tmp)
end
# No harm in leaving the method_missing_tmp there
# self.class.send(:remove_method, :method_missing_tmp)
result
end
end
end
 
# Test class
 
class TestClass
extend Tdef
 
tdef :hello, :a1 => Integer, :a2 => String do
a2 = "Goodbye"
@lala = 999
puts missing_arg
[a1, a2]
end
def method_missing meth, *args, &block
if meth.to_s == "missing_arg"
"lolario"
else
super
end
end
end
 
# Tests
 
describe TestClass do
it "works" do
k = TestClass.new
expect { k.hello }.should_not raise_error(NoMethodError)
r1, r2 = k.hello(10, "Hello")
r1.should eq(10)
r2.should eq("Goodbye")
k.instance_variable_get("@lala").should eq(999)
expect { k.a1 }.should raise_error(NoMethodError)
expect { k.a2 }.should raise_error(NoMethodError)
defined?(a1).should be_nil
defined?(a2).should be_nil
end
it "detects wrong arguments" do
k = TestClass.new
expect { k.hello(10, 20) }.should raise_error
expect { k.hello("Hello", "World") }.should raise_error
end
end

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.