A gem is a ruby code that comes with metadata. It gets installed at a specific location in your system depending upon which ruby versions manager(rvm) such as rvmrc, rbenv and so on, and if not rvm then how you have installed the ruby. You can see this specific location by using the command gem environment
and loop for INSTALLATION DIRECTORY
environment variable.
All gems reside in the gems
directory.
To use a gem, you need to use the code require 'learn_to_code'
. As the definition of require
says, "The file will be searched for in the library directories listed in $LOAD_PATH
. If the file named cannot be found, a LoadError
will be raised".
If we check the content of the $LOAD_PATH
before and after the command require
we will see what changes require
makes for $LOAD_PATH
.
You can see the path for the gem learn_to_code
is now available in a variable $LOAD_PATH
after executing the require 'learn_to_code'
command. So how does that happen? The magic is in RubyGem's code. RubyGem overrides the require
method of the Ruby inside the core_ext/kernel_require.rb
file.
##
# When RubyGems is required, Kernel#require is replaced with our own which
# is capable of loading gems on demand.
#
# When you call <tt>require 'x'</tt>, this is what happens:
# * If the file can be loaded from the existing Ruby loadpath, it
# is.
# * Otherwise, installed gems are searched for a file that matches.
# If it's found in gem 'y', that gem is activated (added to the
# loadpath).
#
# The normal <tt>require</tt> functionality of returning false if
# that file has already been loaded is preserved.
def require path
Since require
command fails to find the gem so it raises an error here. After that, it tries to find the gem using metadata available to RubyGem here.
Once the spec was found, it is activated by the code spec.activate
and $LOAD_PATH
will have access to the gem.
Now the gem is in the load path and can be accessed using the older ruby command gem_original_require
which is an older ruby's version of require
command. And it can also be accessed by using RubyGem's version of require
.