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