include In last week's tip, we learned about ancestors . This set us up to learn about three ways of using code from a module in a class. This week, we'll discuss what is likely the most common of these approaches: include . We can look at an example of using include to include a module's methods in a class: module ExampleModule
def example_method
"This is defined in the module we're including"
end
end
class ExampleClass
include ExampleModule
end
ExampleClass.new.example_method
=> "This is defined in the module we're including"
What is actually happening when we include ExampleModule , or include any module or class, is that this module or class will be inserted in the ancestors chain directly after the class which include s it: ExampleClass.ancestors
=> [ExampleClass, ExampleModule, Object, Kernel, BasicObject]
As we learned last week, this means that Ruby will first look for a method defined on ExampleClass , and if it's not defined there, it will continue to traverse the list of ancestors, looking next at ExampleModule . This means using include gives us the helpful property of being able to easily override methods defined in an included module: module ExampleModule
def example_method
"This is defined in the module we're including"
end
end
class ExampleClass
include ExampleModule
def example_method
"This is defined in ExampleClass itself"
end
end
ExampleClass.new.example_method
=> "This is defined in ExampleClass itself"
If we're used to using include , we might have an intuitive understanding of this overriding in action. Hopefully now with the context around ancestors , we can see why it's happening. In the coming weeks, we'll have tips around two other ways of using code from modules or classes: extend and prepend . |