Ruby autoload class
·In Ruby a common way to load classes is using require. recently I realized that in large projects with lots of classes this approach has some significant problems:
- Loading all class at project bootstrap causes unnecessary overhead.
- Unclear definition of modules and classes.
- Difficaulty in adding/removing classes and modules.
Let’s see an example, I’ve a module with some other modules and classes defined like this:
File: lib/boynux.rb
module Boynux
end
require 'lib/boynux/module1/class1'
require 'lib/boynux/module1/class2'
require 'lib/boynux/module1/module12/another_class1'
require 'lib/boynux/module2/another_class1'
require 'lib/boynux/module3/class3'
...
As you see the code is not very clear which modules and classes are nested. You’ll need to closely examine class path to understand that. When those require statements grow bigger and bigger. Things get more complex and tedius. Finally it’s more probable to make mistakes in defining classes and modules.
The Solution
To solve above problems, we can use Ruby autoload method, defined in Module class. First of all autoload loads classes whenever you try to access them, meaning you don’t need to load all classes at bootstrap stage of your app. This will add a significant performance to your application bootstrap stage. Secondly, your modules and classes will be more clear and easier to maintain. and finally refactoring your project adding/removing and moving classes and modules are a lot easier.
Let’s see how we can refactor above code with autoload and you can see the result.
File: lib/boynux.rb
module Boynux
module Module1
autoload :Class1, 'lib/boynux/module1/class1'
autoload :Class2, 'lib/boynux/module1/class2'
module Module12
autoload :AnotherClass1, 'lib/boynux/module1/another_class1'
end
end
module Module2
autoload :AnotherClass1, 'lib/boynux/module2/another_class1'
end
module Module3
autolaod :Class3, 'lib/boynux/module3/class3'
end
end
Personnay I prefer autoload feature and latest approach rather than requireing all clases like first example.
autoload syntax is very simple and clear, first argument is a class name symbol and second argument a path to the actual class’ source.
You can find more info about autoload at ruby docs Module#autoload
Of course this apporach also have its own drawbacks, namely if you make a typo in class path won’t know that unless you try to access that class somewhere in the code. Which might cause unexpected runtime exceptions (assuming you have decent unit test in place this shouldn’t be a big problem anyway).
I’d love to hear your thoughts about this feature and wheather you’re currently using it or not. Please leave your comments below.