Including Modules from Files

So far, I’ve mixed in modules that have been defined within a single source file. Often it is more useful to define modules in separate files and mix them in as needed. The first thing you have to do in order to use code from another file is to load that file using the require method, like this:

require_module.rb

require( "./testmod.rb" )

Optionally, you may omit the file extension:

require( "./testmod" )  # this works too

If no path is given, the required file must be in the current directory, on the search path, or in a folder listed in the predefined array variable $:. You can add a directory to this array variable using the usual array-append method, <<, in this way:

$: << "C:/mydir"

Note

The global variable, $: (a dollar sign and a colon), contains an array of strings representing the directories that Ruby searches when looking for a loaded or required file.

There is one documented difference in the way require works in Ruby 1.8 and Ruby 1.9. In Ruby 1.8, the filename is not converted to an absolute path, so require "a"; require "./a" will load a.rb twice. In Ruby 1.9, the filename is converted to an absolute path, so require "a"; require "./a" will not load a.rb twice.

In addition, I’ve found that require may, in at least some versions of Ruby 1.9, fail to load a file from the current directory if you use an unqualified filename as in require("testmod"). In such cases, a LoadError is thrown. This occurs when the array of searchable directories stored in the global variable, $:, does not contain the current directory. You can verify whether this is the case by running this code:

search_dirs.rb

puts( $: )

The search paths will be displayed one per line. There should be a line that displays a single dot (.) representing the current directory. If that dot is missing, then files in the current directory are not on the search path and cannot be loaded using an unqualified filename.

To ensure that the file is loaded, I have preceded the filename with a dot to specify the current directory, and this now succeeds: require( "./testmod" ). Alternatively, you could use the require_relative method, though this is new to Ruby 1.9 and cannot be used in earlier versions:

require_relative( "testmod.rb" )    # Ruby 1.9 only

Alternatively, if $: doesn’t contain the current directory, you could add it. Once this is done, require will work with the unqualified names of files in the current directory:

$: << "."              # add current directory to array of search paths
require( "testmod.rb" )

The require method returns a true value if the specified file is successfully loaded; otherwise, it returns false. If the file does not exist, it returns a LoadError. If in doubt, you can simply display the result.

puts(require( "testmod.rb" )) #=> true, false or LoadError

Any code that would normally be executed when a file is run will be executed when that file is required. So, if the file, testmod.rb, contains this code:

testmod.rb

def sing
    puts( "Tra-la-la-la-la....")
end

puts( "module loaded")
sing

when the require_module.rb program is run and it requires testmod.rb, this will be displayed:

module loaded
Tra-la-la-la-la....

When a module is declared in the required file, it can be mixed in:

require_module2.rb
require( "testmod.rb")
include MyModule       #mix in MyModule declared in testmod.rb

Ruby also lets you load a file using the load method. In most respects, require and load can be regarded as interchangeable. But there are a few subtle differences. In particular, load can take an optional second argument, which, if this is true, loads and executes the code as an unnamed or anonymous module:

load( "testmod.rb", true)

When the second argument is true, the file loaded does not introduce the new namespace into the main program, and you will not have access to the module(s) in the loaded file. In that case, the Module methods, constants, and instance methods will not be available to your code:

load_module.rb

load( "testmod.rb", true)

puts( MyModule.greet )   #=>Error:uninitialized constant Object::MyModule
puts(MyModule::GOODMOOD) #=>Error:uninitialized constant Object::MyModule
include MyModule         #=>Error:uninitialized constant Object::MyModule
puts( greet )            #=>Error:undefined local variable or method 'greet'

When the second argument to load is false or when there is no second argument, however, you will have access to modules in the loaded file:

load_module_false.rb

load( "testmod.rb", false)

puts( MyModule.greet )   #=> I'm grumpy. How are you?
puts(MyModule::GOODMOOD) #=> happy
include MyModule         #=> [success]
puts( greet )            #=> I'm happy. How are you?

Note that you must enter the full filename with load (testmod minus the .rb extension will not suffice). Another difference between load and require is that require loads a file once only (even if your code requires that file many times), whereas load causes the specified file to be reloaded each time load is called. Let’s suppose you have a file, test.rb, containing this code:

test.rb

MyConst = 1
if @a == nil then
    @a = 1
else
    @a += MyConst
end

puts @a

You now require this file three times:

require_again.rb

require "./test"
require "./test"
require "./test"

This will be the output:

1

But if you load the file three times . . .

load_again.rb

load "test.rb"
load "test.rb"
load "test.rb"

then this will be the output:

1
./test.rb:1: warning: already initialized constant MyConst
2
./test.rb:1: warning: already initialized constant MyConst
3
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.52.188