Skip to content

Instantly share code, notes, and snippets.

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 JoshCheek/067972f0544f55c75b7794f1c28235f8 to your computer and use it in GitHub Desktop.
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
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