Skip to content

Instantly share code, notes, and snippets.

@frsyuki
Created September 19, 2017 08:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save frsyuki/c9e4a6742b5ae007abe7e7b7dad1ff5f to your computer and use it in GitHub Desktop.
Save frsyuki/c9e4a6742b5ae007abe7e7b7dad1ff5f to your computer and use it in GitHub Desktop.
module HasSize
def size
end
end
module MethodTypeCheckable
def method_type_check(name, signature)
origin = self.instance_method(name)
define_method(name) do |*args, &block|
ok = signature.each_with_index.map do |s,i|
args[i].is_a?(s) || s.public_instance_methods.all? do |required_method_name|
required_params = s.instance_method(required_method_name).parameters
actual_params = args[i].method(required_method_name).parameters rescue nil
required_params == actual_params
end
end.all?
unless ok
raise ArgumentError, "Type check failed"
end
origin.bind(self).call(*args, &block)
end
end
end
class MyService
extend MethodTypeCheckable
def initialize
@map = {}
end
def set(key, value)
@map[key] = value
end
method_type_check :set, [String, String]
def lookup_common_prefix(key)
key.size.times.map do |i|
@map[key[0, i]]
end
end
method_type_check :lookup_common_prefix, [HasSize]
end
class StringLike < String
end
sv = MyService.new
sv.set("type", "checking") #=> ok
sv.set("type", StringLike.new("checking")) #=> ok
sv.lookup_common_prefix("ty") #=> ok
sv.lookup_common_prefix(Time.now) #=> Type check failed (ArgumentError)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment