Guest User

Untitled

a guest
Dec 13th, 2017
66
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 1.45 KB | None | 0 0
  1. module Types
  2. InvalidTypeError = Class.new(ArgumentError)
  3.  
  4. def specify(spec, a_method)
  5. args_spec = []
  6. return_spec = nil
  7. case spec.first
  8. when Hash
  9. args_spec = spec.first.keys.first
  10. return_spec = spec.first.values.first
  11. when Array
  12. args_spec = spec.first
  13. else
  14. args_spec = spec
  15. end
  16.  
  17. original_method = :"_#{a_method}_without_type_checking"
  18. alias_method original_method, a_method
  19. define_method(a_method) do |*args|
  20. ensure_correct_types(args_spec, args)
  21. result = send(original_method, *args)
  22. ensure_correct_types(return_spec, [result], what: "return value") if return_spec
  23. result
  24. end
  25.  
  26. a_method
  27. end
  28.  
  29. module InstanceMethods
  30. def ensure_correct_types(spec, args, what: "argument")
  31. Array(spec).each.with_index do |klass, index|
  32. raise InvalidTypeError, ["Type for #{what}:", klass, "for" , args[index]&.inspect || "-missing #{index.succ} argument-", args[index].class].join(" ") if klass && !(klass === args[index])
  33. end
  34. end
  35. end
  36. private_constant :InstanceMethods
  37.  
  38.  
  39. def self.extended(mod)
  40. mod.include InstanceMethods
  41. end
  42. end
  43.  
  44. Object.extend Types
  45.  
  46. class Foo
  47. specify [String],
  48. def foo(arg)
  49. 42
  50. end
  51.  
  52. specify [String => Numeric],
  53. def bar(arg)
  54. 42
  55. end
  56.  
  57. specify [[String, String]],
  58. def foo2(arg1, arg2)
  59. 42
  60. end
  61.  
  62. specify [[String, String] => Numeric],
  63. def bar2(arg1, arg2)
  64. 42
  65. end
  66. end
  67.  
  68.  
  69. Foo.new.foo("42")
  70. Foo.new.bar2("42", ?x)
Add Comment
Please, Sign In to add comment