Ruby gives methods the ability to call up to the superclass definition of themselves. Or it may not be a parent class definition; it might call up to a definition in a module included further up the ancestor chain. Either way, it’s an elegant way to build on the functionality of class ancestors.
But sometimes you may not know if there is a superclass method to be called. For instance, you may be writing a module. You want the module methods to delegate back to their superclass definitions if those definitions exist; but you don’t want the code to crash with a NoMethodError if they don’t exist. What to do?
As always, Ruby gives us the tools we need. defined?
to the rescue:
module Stuff def foo puts "In Stuff#foo" if defined?(super) puts "Calling super" super else puts "No super" end end end module OtherStuff def foo puts "In OtherStuff#foo" end end class NoSuper include Stuff end NoSuper.new.foo # >> In Stuff#foo # >> No super class WithSuper include OtherStuff include Stuff end WithSuper.new.foo # >> In Stuff#foo # >> Calling super # >> In OtherStuff#foo
defined?
is a built-in Ruby operator (not an ordinary method!) which can tell you if a given method or variable has been defined. It also works for determining if a super method exists somewhere in the ancestor chain. Use defined?(super)
to write generic modules that play well with others.
Quick note, this fails with
SimpleDelegator
becauseself
is not the wrapped object but the delegator object. This is what I came up with instead:def description; __getobj__.respond_to?(__method__) ? super : 'No description'; end
.Thank you so much Kris Leech. I was looking for the exact solution