Automatically Loading Libraries as Needed

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



Ruby Cookbook
Ruby Cookbook (Cookbooks (OReilly))
ISBN: 0596523696
EAN: 2147483647
Year: N/A
Pages: 399

Flylib.com © 2008-2020.
If you may any questions please contact us: flylib@qtcs.net