Include, extend, and then get fancy.
include
: makes instance methods from module as instance methods
When you include a module inside class.
- All the instance method from the module becomes instance method for the instances of that class.
- All singleton or class methods from the module are not accessible from either instance or class. We will discuss soon.
extend
: makes instance methods from module as class methods
When you extend a module inside class
- All the instance method from the module becomes singleton method of that class.
- All the singleton method from the module becomes are not accessible from either instance of class. We will discuss.
Let learn by example.
What happens when we include module A
containing both instance method and class method inside class Test
module A
def foo
puts 'foo'
end
def self.bar
puts 'bar'
end
end
class Test
include A
end
Test.new.foo
#=> foo
Test.foo
#=> undefined method `foo' for Test:Class (NoMethodError)
Test.new.bar
#=> undefined method `bar' for #<Test:0x000000012984f330> (NoMethodError)
Test.bar
#=> undefined method `bar' for Test:Class (NoMethodError)
What happens when we extend module A
inside class Test
module A
def foo
puts 'foo'
end
def self.bar
puts 'bar'
end
end
class Test
extend A
end
Test.new.foo
#=> undefined method `foo' for #<Test:0x000000014a106eb8> (NoMethodError)
Test.foo
#=> foo
Test.new.bar
#=> undefined method `bar' for #<Test:0x000000014791b228> (NoMethodError)
Test.bar
#=> undefined method `bar' for Test:Class (NoMethodError)
What if we want to include a module having both instance and class level methods, and include both instance and class level methods. We can do it this way. Explanation after the example.
module A
def foo
puts 'foo'
end
# Define all your singleton or class level methods here. Notice that we are not using `self`
# reference here.
module ClassMethods
def bar
puts 'bar'
end
end
# This is a hook which will run when the module is included by another module. `base` is
# the class that included the module. Then we just `extend` all methods inside module
# `ClassMethods` so that those methods become singleton inside the base class.
def self.included(base)
base.extend ClassMethods
end
end
class Test
include A
end
Test.new.foo
#=> foo
Test.bar
#=> bar
Test.new.bar
#=> undefined method `bar' for #<Test:0x0000000129186eb8> (NoMethodError)