Problem
You've written a big library with multiple components. You'd like to split it up so that users don't have to load the entire library into memory just to use part of it. But you don't want to make your users explicitly require each part of the library they plan to use.
Solution
Split the big library into multiple files, and set up autoloading for the individual files by calling Kernel#autoload. The individual files will be loaded as they're referenced.
Suppose you have a library, functions.rb, that provides two very large modules:
# functions.rb module Decidable # … Many, many methods go here. end module Semidecidable # … Many, many methods go here. end
You can provide the same interface, but possibly save your users some memory, by splitting functions.rb into three files. The functions.rb file itself becomes a stub full of autoload calls:
# functions.rb autoload :Decidable, "decidable.rb" autoload :Semidecidable, "semidecidable.rb"
The modules themselves go into the files mentioned in the new functions.rb:
# decidable.rb module Decidable # … Many, many methods go here. end # semidecidable.rb module Semidecidable # … Many, many methods go here. end
The following code will work if all the modules are in functions.rb, but it will also work if functions.rb only contains calls to autoload:
require 'functions' Decidable.class # => Module # More use of the Decidable module follows…
When Decidable and Semidecidable have been split into autoloaded modules, that code only loads the Decidable module. Memory is saved that would otherwise be used to contain the unsed Semidecidable module.
Discussion
Refactoring a library to consist of autoloadable components takes a little extra planning, but it's often worth it to improve performance for the people who use your library.
Each call to Kernel#autoload binds a symbol to the path of the Ruby file that's supposed to define that symbol. If the symbol is referenced, that file is loaded exactly as though it had been passed as an argument into require. If the symbol is never referenced, the user saves some memory.
Since you can use autoload wherever you might use require, you can autoload builtin libraries when the user triggers some code that needs them. For instance, here's some code that loads Ruby's built-in set library as needed:
autoload :Set, "set.rb" def random_set(size) max = size * 10 set = Set.new set << rand(max) until set.size == size return set end # More code goes here…
If random_set is never called, the set library will never be loaded, and memory will be saved. As soon as random_set gets called, the set library is autoloaded, and the code works even though we never explicitly require 'set':
random_set(10) # => # require 'set' # => false
Strings
Numbers
Date and Time
Arrays
Hashes
Files and Directories
Code Blocks and Iteration
Objects and Classes8
Modules and Namespaces
Reflection and Metaprogramming
XML and HTML
Graphics and Other File Formats
Databases and Persistence
Internet Services
Web Development Ruby on Rails
Web Services and Distributed Programming
Testing, Debugging, Optimizing, and Documenting
Packaging and Distributing Software
Automating Tasks with Rake
Multitasking and Multithreading
User Interface
Extending Ruby with Other Languages
System Administration