#Modules & Mixins ####CapitalizedCamelCase
You can think of a module as a toolbox that contains a set methods and constants. We keep a bunch of them in modules and only pull in those module toolboxes when we need the constants and methods inside!
You can think of modules as being very much like classes, only modules can't create instances and can't have subclasses. They're just used to store things!
module Circle
PI = 3.141592653589793
def Circle.area(radius)
PI * radius**2
end
def Circle.circumference(radius)
2 * PI * radius
end
end
One of the main purposes of modules is to separate methods and constants into named spaces. This is called (conveniently enough) namespacing, and it's how Ruby doesn't confuse Math::PI and Circle::PI.
See that double colon we just used? That's called the scope resolution operator, which is a fancy way of saying it tells Ruby where you're looking for a specific bit of code. If we say Math::PI, Ruby knows to look inside the Math module to get that PI, not any other PI (such as the one we created in Circle).
require 'module'
Some modules, like Math, are already present in the interpreter. Others need to be explicitly brought in, however, and we can do this using require.
include module
Any class that includes a certain module can use those module's methods! A nice effect of this is that you no longer have to prepend your constants and methods with the module name. Since everything has been pulled in, you can simply write PI instead of Math::PI.
module Action
def jump
@distance = rand(4) + 2
puts "I jumped forward #{@distance} feet!"
end
end
class Rabbit
include Action
attr_reader :name
def initialize(name)
@name = name
end
end
class Cricket
include Action
attr_reader :name
def initialize(name)
@name = name
end
end
peter = Rabbit.new("Peter")
jiminy = Cricket.new("Jiminy")
peter.jump
jiminy.jump
Mixin - When a module is used to mix additional behavior and information into a class, it's called a mixin. Mixins allow us to customize a class without having to rewrite code!
# ThePresent has a .now method that we'll extend to TheHereAnd
module ThePresent
def now
puts "It's #{Time.new.hour > 12 ? Time.new.hour - 12 : Time.new.hour}:#{Time.new.min} #{Time.new.hour > 12 ? 'PM' : 'AM'} (GMT)."
end
end
class TheHereAnd
extend ThePresent
end
TheHereAnd.now
Extend - The extend keyword mixes a module's methods at the class level. This means that class itself can use the methods, as opposed to instances of the class.