prepend We'll continue our brief Tip Of Week series around using code from a module by learning about prepend . Last week, we learned about include, and how it inserts a module into the ancestors chain directly after the class which includes it. prepend uses the same syntax as include but works differently - it inserts a module into the ancestors chain directly before the class which includes it. Let's take a look:
module ExampleModule
def example_method
"This is defined in the module we're prepending"
end
end
class ExampleClass
prepend ExampleModule
end
ExampleClass.new.example_method
=> "This is defined in the module we're prepending"
Now if we look at the ancestors chain, we'll see that ExampleModule precedesExampleClass . This is the exact opposite of what we saw last week with ExampleModule succeedingExampleClass : ExampleClass.ancestors
=> [ExampleModule, ExampleClass, Object, Kernel, BasicObject]
As we learned when discussing ancestors, this means that Ruby will first look for a method defined on ExampleModule , and if it's not defined there, it will continue to traverse the list of ancestors, looking next at ExampleClass (our class itself). This means using prepend will cause the methods defined on the module we're prepending to trump methods defined on the class itself. module ExampleModule
def example_method
"This is defined in ExampleModule, which we're prepending"
end
end
class ExampleClass
prepend ExampleModule
def example_method
"This is defined in ExampleClass itself"
end
end
ExampleClass.new.example_method
=> "This is defined in ExampleModule, which we're prepending"
prepend is commonly used in cases where it makes sense for a module to override a method defined in a class. Examples of this might be when a module needs to set something up in the initialize method, but the initialize method of a class itself doesn't call super . The initialize method in the module can do whatever setup it needs, and then call super to execute the class' initialize method.
We'll learn about extend next week! |