Last active
June 6, 2018 21:44
-
-
Save JoshCheek/067972f0544f55c75b7794f1c28235f8 to your computer and use it in GitHub Desktop.
Example of how you could compare two classes to make sure their interfaces match
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class LHS | |
def correct() end | |
def wrong_num_args(a) end | |
def wrong_arg_types(a,b:) end | |
def wrong_name(a) end | |
def lhs_only() end | |
end | |
class RHS | |
def correct() end | |
def wrong_num_args(a, b) end | |
def wrong_arg_types(a, b) end | |
def wrong_name(b) end | |
def rhs_only() end | |
end | |
def compare_interfaces(lhs, rhs) | |
methods = lhs.instance_methods(false) | rhs.instance_methods(false) | |
methods.map do |name| | |
lhsm = (lhs.instance_method(name) rescue nil) | |
rhsm = (rhs.instance_method(name) rescue nil) | |
[name, lhsm&.parameters, rhsm&.parameters] | |
end | |
end | |
def pretty_params(parameters) | |
return "missing" unless parameters | |
pretty_params = parameters.map do |type, name| | |
case type | |
when :req then name | |
when :opt then "#{name}=..." | |
when :rest then "*#{name}" | |
when :keyreq then "#{name}:" | |
when :key then "#{name}:..." | |
when :keyrest then "**#{name}" | |
when :block then "&#{name}" | |
else raise "huh? #{type.inspect}" | |
end | |
end | |
"(#{pretty_params.join ', '})" | |
end | |
def assert_interfaces!(lhs, rhs) | |
desc = compare_interfaces(lhs, rhs) | |
.reject { |_, l, r| l == r } | |
.map { |name, l, r| <<~MSG.gsub /^/, " " } | |
##{name} | |
#{lhs}: #{pretty_params l} | |
#{rhs}: #{pretty_params r} | |
MSG | |
.join("\n") | |
raise TypeError, "Interface mismatch:\n#{desc}", caller | |
end | |
assert_interfaces! LHS, RHS # ~> TypeError: Interface mismatch:\n #wrong_num_args\n LHS: (a)\n RHS: (a, b)\n\n #wrong_arg_types\n LHS: (a, b:)\n RHS: (a, b)\n\n #wrong_name\n LHS: (a)\n RHS: (b)\n\n #lhs_only\n LHS: ()\n RHS: missing\n\n #rhs_only\n LHS: missing\n RHS: ()\n | |
# ~> TypeError | |
# ~> Interface mismatch: | |
# ~> #wrong_num_args | |
# ~> LHS: (a) | |
# ~> RHS: (a, b) | |
# ~> | |
# ~> #wrong_arg_types | |
# ~> LHS: (a, b:) | |
# ~> RHS: (a, b) | |
# ~> | |
# ~> #wrong_name | |
# ~> LHS: (a) | |
# ~> RHS: (b) | |
# ~> | |
# ~> #lhs_only | |
# ~> LHS: () | |
# ~> RHS: missing | |
# ~> | |
# ~> #rhs_only | |
# ~> LHS: missing | |
# ~> RHS: () | |
# ~> | |
# ~> /var/folders/7g/mbft22555w3_2nqs_h1kbglw0000gn/T/seeing_is_believing_temp_dir20180606-89092-tr75on/program.rb:55:in `<main>' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment