load, autoload, require and require_relative.
Ruby will look in it's $LOAD_PATH global variable for a list of directories to look for ruby files.
Open pry and look at the $LOAD_PATH
pry(main)> $LOAD_PATH
pry(main)> $:
This will reload the ruby file every time it's called. Good for debugging.
pry(main)> load 'calendar.rb'
change the file
pry(main)> load './calendar.rb'
notice the changes
pry(main)> load './calendar'
Must have the .rb on the file name to load.
This will load a ruby file ONCE. All subsequent require statements will not load the file.
*Doesn't need the .rb file extension, but won't hurt if it's there. *Does need the relative path './'.
pry(main)> require './calendar'
change the file
pry(main)> require './calendar'
notice the changes are NOT seen!
Problem with Kernel#relative is that the relative path is relative to where ruby was invoked/executed. Its not relative to where the file resides.
In the show_person.rb file we use this require to try to load the Person class.
require './lib/person'
...
When we run this in the root directory of this project it will work. Because it's looking for the file defining the Person class, person.rb, in the child directory 'lib'.
$ ruby bin/show_person.rb
OK, if we run it in the root directory
$ cd bin
If we cd into the bin directory and try to run this it will fail.
$ ruby show_person.rb
Fails, it's looking for the file in bin/lib/person.rb `require': cannot load such file -- ./lib/person (LoadError)
The fix is to use require_relative. This will try to find the file relative to the file that has that has the require_relative statement.
- In bin/show_person.rb:
- uncomment require_relative '../lib/person'
- comment out require './lib/person'
$ ruby bin/show_person.rb
Still OK, if run it in the root directory.
$ cd bin
$ ruby show_person.rb
Still OK
$ cd ../tmp
$ ruby ../bin/show_person.rb
Still OK.
You may run across an older hack for this problem. It adds the current directory of the file in the Ruby load path. DON'T USE THIS.
$LOAD_PATH.unshift("#{File.dirname(__FILE__)}/../lib")
- Create Person class, in the lib dir, that has name and age attributes. It will also have a method to determine if person can vote. Initially a person can vote if the are over 18.
- Open pry and "load" this person class.
- Create a person that is age 19.
- Can they vote?
- Now change the person class so that the voting age is now 21.
- load the person class. Was the change seen?
- Do the above for require and require relative.
This will create voters of different ages, some to young to vote.
-
In the lib/make_voters.rb file add this to the top of file. require '../lib/person'
-
Run the command from the root directory "ruby bin/make_voters.rb"
-
Run the command from the bin directory "cd bin; ruby make_voters.rb"
-
Run the command from your HOME directory "cd ~; ruby your path here/make_voters.rb"
-
Change the require in this file to require_relative and do the above.