Using modules in crystal
As your application grows, you would like to move from one big .cr file to separating your code into smaller files.
You can use require from your main .cr file to add code from other files:
require “./tools/*”
This statement will add code from the tools directory, relative to your main .cr file.
This will help to separate your application “physically”, but it also may be desirable to separate it logically – maybe some of the code can be reused in other projects, and maybe you also want to avoid namespace collisions.
What is a namespace collision?
If a method or class name, or constant name is used two times in different source files in the global namespace, you will have a collision.
How is the compiler supposed to know, which method / class you actually want of the two which are defined?
To avoid namespace collisions you separate your code into modules.
for instance:
module Debug
class SampleClass
end
SAMPLE_CONSTANT = “some value”
macro samplemacro(some_variable)
#some macro code
end
#your code goes here
end
Accessing code in modules
Now you can access the code (after having required the file the module is defined in) like this:
sampleinstance = Debug::SampleClass.new()
p Debug::SAMPLE_CONSTANT
Debug.samplemacro
Note that a macro is called with a “.” syntax, not a “:” syntax. You can consider it as a method of the Module.
Including modules
If, on the other hand, you find the additional notation tiresome, you can include the module using it’s method name like this:
include Debug
then you will be able to access the methods, classes, constants and macros without any additional notation – as if the code was literally copy & pasted into your other source file:
sampleinstance = SampleClass.new()
p SAMPLE_CONSTANT
samplemacro