Ruby include vs included vs extend
Mixins vs Inheritance
Mixins and Inheritance are a way to share functionality with other classes or module.
Inheritance has the disadvantage that you can only extend only one class.
Mixins however are included, you can include as many mixins as you would like. Using mixins is the preferred way to share behaviours and organize code using composition.
The Ancestors chain
When a ruby class is created it contains constant names, these are classes they inherit from.
When we are comparing strings we use the Comparable ancestor e.g ==
include
This inserts our module just after the super class (AnotherService).
module CustomService
def log(level, message)
puts "We are logging #{level} #{message}"
end
end
class AnotherService
include CustomService
def do_something
begin
# do something
rescue StandardError => e
log :error, e.message
end
end
end
extend
If we swap the include with extend then the method log is available in AnotherService as a static/class method.
module CustomService
def log(level, message)
puts "We are logging #{level} #{message}"
end
end
class AnotherService
extend CustomService
def do_something
begin
# do something
rescue StandardError => e
log :error, e.message
end
end
end
prepend
module CustomService
def log(level, message)
puts "We are logging #{level} #{message}"
end
end
class AnotherService
prepend CustomService
def do_something
begin
# do something
rescue StandardError => e
log :error, e.message
end
end
end
Prepend works like include except it inserts the class at the bottom of the ancestor chain. This can be useful if you have some code you would like to run before anything else.