How does a gem work?

In this article we are going to explore the working of a gem.

·

2 min read

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.