When you call a method on an object, Ruby looks for the implementation of that method. It looks in the following places and uses the first implementation it finds:
Let's say we have the following class hierarchy:
class Superclass
def action
puts "Superclass"
end
end
module IncludedModule
def action
puts "Included module"
super
end
end
module PrependedModule
def action
puts "Prepended module"
super
end
end
module SingletonModule
def action
puts "Singleton class"
super
end
end
class Klass < Superclass
include IncludedModule
prepend PrependedModule
def action
puts "Klass"
super
end
end
... and we call a method like this:
instance = Klass.new
instance.extend(SingletonModule)
instance.action
Then we get an output as expected:
Singleton class
Prepended module
Klass
Included module
Superclass
If you are interested in why it works like that, you will find some more background here.