syntax.us Let the syntax do the talking
Blog Contact Posts Questions Tags Hire Me

Question:
Ruby: GEM_HOME, GEM_PATH do what?

Ruby is a modular language.

I use RubyGems to build Ruby applications from other developers' reusable Ruby code.

I find RubyGems at this site:

https://rubygems.org/

Perhaps the most well known RubyGem is 'Ruby on Rails' AKA Rails:

https://rubygems.org/gems/rails

When I study the above page I see the modular nature of Ruby because I notice that Rails depends on many other gems.

On my Ubuntu laptop I recently installed Ruby with a simple shell command:
apt-get install ruby ruby-dev
Next, I created a folder for a demo app:
mkdir /tmp/demo1
Then, I attached a RubyGem folder to the app:
mkdir /tmp/demo1/gems
Next, I copied a RubyGem into the folder with the help of the GEM_HOME shell variable:
export GEM_HOME=/tmp/demo1/gems
gem install haml
ls -la /tmp/demo1/gems
I see GEM_HOME as part of a 'setter mechanism'. Above, It sets, or declares, that /tmp/demo1/gems will be the home of any RubyGems which I may install in the future.

Then, I added more folders to /tmp/demo1/
mkdir /tmp/demo1/bin /tmp/demo1/haml /tmp/demo1/html
Next, I created a simple haml file, /tmp/demo1/haml/index.haml, which looks like this:

%html
  %head
    %title hello world
  %body
    #div1.simple_div
      I can use haml to create html.
  :javascript
    alert('JavaScript can be in haml files');
Then, I created a shell script which uses GEM_PATH as part of a 'getter mechanism':
#!/bin/bash

# runme.bash

cd /tmp/demo1/

export GEM_PATH=/tmp/demo1/gems

$GEM_PATH/bin/haml /tmp/demo1/haml/index.haml /tmp/demo1/html/index.html 

cat /tmp/demo1/html/index.html 

exit
In the above script, I use GEM_PATH to declare that my app will get RubyGems from this folder:
/tmp/demo1/gems
I avoid getting RubyGems from the default location which might be under /var/lib/ somewhere.

To find the default folders where Ruby searches for RubyGems, I run three shell commands:
dan@usb99:/tmp/demo1 $ 
dan@usb99:/tmp/demo1 $ unset GEM_HOME GEM_PATH
dan@usb99:/tmp/demo1 $ 
dan@usb99:/tmp/demo1 $ which gem
/usr/bin/gem
dan@usb99:/tmp/demo1 $ 
dan@usb99:/tmp/demo1 $ gem env
RubyGems Environment:
  - RUBYGEMS VERSION: 1.8.23
  - RUBY VERSION: 1.9.3 (2013-11-22 patchlevel 484) [x86_64-linux]
  - INSTALLATION DIRECTORY: /var/lib/gems/1.9.1
  - RUBY EXECUTABLE: /usr/bin/ruby1.9.1
  - EXECUTABLE DIRECTORY: /usr/local/bin
  - RUBYGEMS PLATFORMS:
    - ruby
    - x86_64-linux
  - GEM PATHS:
     - /var/lib/gems/1.9.1
     - /home/dan/.gem/ruby/1.9.1
  - GEM CONFIGURATION:
     - :update_sources => true
     - :verbose => true
     - :benchmark => false
     - :backtrace => false
     - :bulk_threshold => 1000
     - "gem" => "--no-ri --no-rdoc"
     - "install" => "--env-shebang"
     - "update" => "--env-shebang"
     - :sources => ["http://rubygems.org", "http://gems.github.com"]
  - REMOTE SOURCES:
     - http://rubygems.org
     - http://gems.github.com
dan@usb99:/tmp/demo1 $ 
dan@usb99:/tmp/demo1 $ 
When I run the script, /tmp/demo1/bin/runme.bash, I see the following output:
dan@usb99:/tmp/demo1 $ 
dan@usb99:/tmp/demo1 $ /tmp/demo1/bin/runme.bash 
<html>
  <head>
    <title>hello world</title>
  </head>
  <body>
    <div class='simple_div' id='div1'>
      I can use haml to create html.
    </div>
  </body>
  <script>
    alert('JavaScript can be in haml files');
  </script>
</html>
dan@usb99:/tmp/demo1 $ 
dan@usb99:/tmp/demo1 $ 


I prefer to use GEM_HOME and GEM_PATH for simple ruby apps.

The above app, /tmp/demo1, is simple; it uses one gem named haml.

If I have a ruby app which is more complex and depends on many RubyGems, I enhance my use of GEM_HOME.

How?

I use 'Bundler' (which happens to be a RubyGem).

Bundler asks me to use a file named 'Gemfile' to declare which RubyGems my app depends upon.

I keep in mind that Bundler does not replace GEM_HOME; Actually Bundler depends on GEM_HOME.

If I want /tmp/demo1 to use Bundler I create /tmp/demo1/Gemfile.

That file might look like this:
# /tmp/demo1/Gemfile
source 'https://rubygems.org'
gem 'haml','4.0.7'
I use the above Gemfile to declare that my app depends on haml(specifically, version 4.0.7 of haml).

To use bundler I need to install it with this shell command:
gem install bundler
Then I need to use its shell command:

dan@usb99:/tmp/demo1 $ 
dan@usb99:/tmp/demo1 $ export GEM_HOME=/tmp/demo1/gems
dan@usb99:/tmp/demo1 $ export GEM_PATH=/tmp/demo1/gems
dan@usb99:/tmp/demo1 $ 
dan@usb99:/tmp/demo1 $ gem list

*** LOCAL GEMS ***

bundler (1.10.6)
haml (4.0.7)
tilt (2.0.1)
dan@usb99:/tmp/demo1 $ bundle install
The program 'bundle' is currently not installed. You can install it by typing:
sudo apt-get install bundler
dan@usb99:/tmp/demo1 $ 
dan@usb99:/tmp/demo1 $ 


I need to remember that the bundle shell command comes from a RubyGem. So I will find the bundle shell command under $GEM_HOME.
dan@usb99:/tmp/demo1 $ dan@usb99:/tmp/demo1 $ $GEM_HOME/bin/bundle install Fetching gem metadata from https://rubygems.org/..... Fetching version metadata from https://rubygems.org/.. Resolving dependencies... Using tilt 2.0.1 Using haml 4.0.7 Using bundler 1.10.6 Bundle complete! 1 Gemfile dependency, 3 gems now installed. Use `bundle show [gemname]` to see where a bundled gem is installed. dan@usb99:/tmp/demo1 $ dan@usb99:/tmp/demo1 $ dan@usb99:/tmp/demo1 $
The beauty of Bundler is that it declares which RubyGems that an app depends upon.

If I have a Rails app which depends on many different RubyGems, and I also require that some of the RubyGems be specific versions, then the power of Bundler becomes clear.


syntax.us Let the syntax do the talking
Blog Contact Posts Questions Tags Hire Me