As mentioned in the comments by 200_success:
- Why is zero the default, if it's invalid?
- And: What about a negative radius?
Conceptually, a circle with a zero or negative radius might not make a lot of sense, but there's nothing in your code that would break because of it. The area will never be negative since the radius is multiplied by itself. The area might be zero, but again, that is the area of a zero-radius circle, so strictly speaking it's still valid.
You're also checking the type of the radius argument. You can argue either way if that's a good idea. It just raises a RuntimeError, with no extra explanation of what went wrong. If the check wasn't there, and you called, say, Circle.new("banana", "banana").area, you'd just get a NoMethodError instead. Not saying that's better, just saying that it's much worse either. Of course the current check happens in the constructor, which might be nice, but is it necessary?
For most cases, I lean toward saying "Garbage in, garbage out". If you've set the radius to "banana", then don't expect the math to make sense. Since Ruby isn't strictly typed and there's no compile step, the exceptions will occur at runtime anyway. So even if you try to add a lot of type-checking, it's debatable how much value it adds. Especially in this case, since raising a RuntimeError with no extra explanation seems less useful than letting, say, a NoMethodError occur, which will at least tell you things like undefined method**' for "banana"`.
Regardless, no reason to be dogmatic either way; type-checking definitely has its uses, and I'm not saying to always avoid it. Just make sure it adds some value.
Besides, it'd be better to raise an TypeError, since that's a lot more specific to this case than a general things-just-kinda-broke-RuntimeError.
I'd still argue that radius can indeed be zero, and that's fine. It's a strange circle to contemplate, but it's not impossible.
Again, I'd probably just skip the checking entirely, but if I were to add it, I'd write
raise TypeError.new("Radius must be numeric") unless radius.is_a?(Numeric)
And if you do want to avoid strange radii, you can add a separate check after that:
raise ArgumentError.new("Radius must be > 0") if radius <= 0
radius = 0if that is an unacceptable value? \$\endgroup\$